Path: Adaptive - performance optimization for larger models

- utilizing bounding boxes
- changed the alg. for resolving tool down linking paths,
   resolution is no longer based on clipper offsets as
   offset alg. tends to become slow
- new tool down linking alg. also should be better in finding
   shorter linking paths
- lead-in lead-out improvements
This commit is contained in:
kreso-t
2018-09-16 22:05:56 +02:00
committed by wmayer
parent 76638c7c32
commit 46cd140c8b
2 changed files with 2937 additions and 2087 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -19,14 +19,11 @@
* *
***************************************************************************/
#include "clipper.hpp"
#include <vector>
#include <list>
#include <time.h>
#ifndef ADAPTIVE_HPP
#define ADAPTIVE_HPP
@@ -42,118 +39,138 @@
#define M_PI 3.141592653589793238
#endif
//#define DEV_MODE
#define NTOL 1.0e-7 // numeric tolerance
#define NTOL 1.0e-7 // numeric tolerance
namespace AdaptivePath {
using namespace ClipperLib;
namespace AdaptivePath
{
using namespace ClipperLib;
enum MotionType { mtCutting = 0, mtLinkClear = 1, mtLinkNotClear = 2, mtLinkClearAtPrevPass = 3 };
enum MotionType
{
mtCutting = 0,
mtLinkClear = 1,
mtLinkNotClear = 2,
mtLinkClearAtPrevPass = 3
};
enum OperationType { otClearingInside = 0, otClearingOutside = 1, otProfilingInside = 2, otProfilingOutside = 3 };
enum OperationType
{
otClearingInside = 0,
otClearingOutside = 1,
otProfilingInside = 2,
otProfilingOutside = 3
};
typedef std::pair<double,double> DPoint;
typedef std::vector<DPoint> DPath;
typedef std::vector<DPath> DPaths;
typedef std::pair<int,DPath> TPath; // first parameter is MotionType, must use int due to problem with serialization to JSON in python
typedef std::pair<double, double> DPoint;
typedef std::vector<DPoint> DPath;
typedef std::vector<DPath> DPaths;
typedef std::pair<int, DPath> TPath; // first parameter is MotionType, must use int due to problem with serialization to JSON in python
// struct TPath { #this does not work correctly with pybind, changed to pair
// DPath Points;
// MotionType MType;
// };
class ClearedArea;
typedef std::vector<TPath> TPaths;
// struct TPath { #this does not work correctly with pybind, changed to pair
// DPath Points;
// MotionType MType;
// };
struct AdaptiveOutput {
DPoint HelixCenterPoint;
DPoint StartPoint;
TPaths AdaptivePaths;
int ReturnMotionType; // MotionType enum, problem with serialization if enum is used
};
typedef std::vector<TPath> TPaths;
// used to isolate state -> enable potential adding of multi-threaded processing of separate regions
struct AdaptiveOutput
{
DPoint HelixCenterPoint;
DPoint StartPoint;
TPaths AdaptivePaths;
int ReturnMotionType; // MotionType enum, problem with serialization if enum is used
};
class Adaptive2d {
public:
Adaptive2d();
double toolDiameter=5;
double helixRampDiameter=0;
double stepOverFactor = 0.2;
double tolerance=0.1;
double stockToLeave=0;
bool forceInsideOut = true;
double keepToolDownDistRatio = 3.0; // keep tool down distance ratio
OperationType opType = OperationType::otClearingInside;
// used to isolate state -> enable potential adding of multi-threaded processing of separate regions
std::list<AdaptiveOutput> Execute(const DPaths &stockPaths, const DPaths &paths, std::function<bool(TPaths)> progressCallbackFn);
class Adaptive2d
{
public:
Adaptive2d();
double toolDiameter = 5;
double helixRampDiameter = 0;
double stepOverFactor = 0.2;
double tolerance = 0.1;
double stockToLeave = 0;
bool forceInsideOut = true;
double keepToolDownDistRatio = 3.0; // keep tool down distance ratio
OperationType opType = OperationType::otClearingInside;
#ifdef DEV_MODE
/*for debugging*/
std::function<void(double cx,double cy, double radius, int color)> DrawCircleFn;
std::function<void(const DPath &, int color)> DrawPathFn;
std::function<void()> ClearScreenFn;
#endif
std::list<AdaptiveOutput> Execute(const DPaths &stockPaths, const DPaths &paths, std::function<bool(TPaths)> progressCallbackFn);
private:
std::list<AdaptiveOutput> results;
Paths inputPaths;
Paths stockInputPaths;
int polyTreeNestingLimit=0;
double scaleFactor=100;
long toolRadiusScaled=10;
long finishPassOffsetScaled=0;
long helixRampRadiusScaled=0;
long bbox_size=0;
double referenceCutArea=0;
double optimalCutAreaPD=0;
//double minCutAreaPD=0;
bool stopProcessing=false;
long unclearLinkingMoveCount = 0;
#ifdef DEV_MODE
/*for debugging*/
std::function<void(double cx, double cy, double radius, int color)> DrawCircleFn;
std::function<void(const DPath &, int color)> DrawPathFn;
std::function<void()> ClearScreenFn;
#endif
time_t lastProgressTime = 0;
std::function<bool(TPaths)> * progressCallback=NULL;
Path toolGeometry; // tool geometry at coord 0,0, should not be modified
private:
std::list<AdaptiveOutput> results;
Paths inputPaths;
Paths stockInputPaths;
int polyTreeNestingLimit = 0;
double scaleFactor = 100;
long toolRadiusScaled = 10;
long finishPassOffsetScaled = 0;
long helixRampRadiusScaled = 0;
long bbox_size = 0;
double referenceCutArea = 0;
double optimalCutAreaPD = 0;
//double minCutAreaPD=0;
bool stopProcessing = false;
long unclearLinkingMoveCount = 0;
void ProcessPolyNode(Paths boundPaths, Paths toolBoundPaths);
bool FindEntryPoint(TPaths &progressPaths,const Paths & toolBoundPaths,const Paths &bound, Paths &cleared /*output*/,
IntPoint &entryPoint /*output*/, IntPoint & toolPos, DoublePoint & toolDir);
bool FindEntryPointOutside(TPaths &progressPaths,const Paths & toolBoundPaths,const Paths &bound, Paths &cleared /*output*/,
IntPoint &entryPoint /*output*/, IntPoint & toolPos, DoublePoint & toolDir);
double CalcCutArea(Clipper & clip,const IntPoint &toolPos, const IntPoint &newToolPos, const Paths &cleared_paths, bool preventConvetionalMode=true);
void AppendToolPath(TPaths &progressPaths,AdaptiveOutput & output,const Path & passToolPath,const Paths & cleared,const Paths & toolBoundPaths);
bool IsClearPath(const Path & path,const Paths & cleared, double safetyDistanceScaled=0);
bool IsAllowedToCutTrough(const IntPoint &p1,const IntPoint &p2,const Paths & cleared,const Paths & toolBoundPaths, double areaFactor=1.5, bool skipBoundsCheck=false);
time_t lastProgressTime = 0;
friend class EngagePoint; // for CalcCutArea
std::function<bool(TPaths)> *progressCallback = NULL;
Path toolGeometry; // tool geometry at coord 0,0, should not be modified
void CheckReportProgress(TPaths &progressPaths,bool force=false);
void AddPathsToProgress(TPaths &progressPaths,const Paths paths, MotionType mt=MotionType::mtCutting);
void AddPathToProgress(TPaths &progressPaths,const Path pth, MotionType mt=MotionType::mtCutting);
void ApplyStockToLeave(Paths &inputPaths);
private: // constants for fine tuning
const double RESOLUTION_FACTOR = 8.0;
const int MAX_ITERATIONS = 16;
const double AREA_ERROR_FACTOR = 0.05; /* how precise to match the cut area to optimal, reasonable value: 0.05 = 5%*/
const size_t ANGLE_HISTORY_POINTS=3; // used for angle prediction
const int DIRECTION_SMOOTHING_BUFLEN=3; // gyro points - used for angle smoothing
void ProcessPolyNode(Paths boundPaths, Paths toolBoundPaths);
bool FindEntryPoint(TPaths &progressPaths, const Paths &toolBoundPaths, const Paths &bound, ClearedArea &cleared /*output*/,
IntPoint &entryPoint /*output*/, IntPoint &toolPos, DoublePoint &toolDir);
bool FindEntryPointOutside(TPaths &progressPaths, const Paths &toolBoundPaths, const Paths &bound, ClearedArea &cleared /*output*/,
IntPoint &entryPoint /*output*/, IntPoint &toolPos, DoublePoint &toolDir);
double CalcCutArea(Clipper &clip, const IntPoint &toolPos, const IntPoint &newToolPos, ClearedArea &clearedArea, bool preventConvetionalMode = true);
void AppendToolPath(TPaths &progressPaths, AdaptiveOutput &output, const Path &passToolPath, ClearedArea &clearedAreaBefore,
ClearedArea &clearedAreaAfter, const Paths &toolBoundPaths);
bool IsClearPath(const Path &path, ClearedArea &clearedArea, double safetyDistanceScaled = 0);
bool IsAllowedToCutTrough(const IntPoint &p1, const IntPoint &p2, ClearedArea &clearedArea, const Paths &toolBoundPaths, double areaFactor = 1.5, bool skipBoundsCheck = false);
bool MakeLeadPath(bool leadIn, const IntPoint &startPoint, const DoublePoint &startDir, const IntPoint &beaconPoint,
ClearedArea &clearedArea, const Paths &toolBoundPaths, Path &output);
const double ENGAGE_AREA_THR_FACTOR=0.2; // influences minimal engage area (factor relation to optimal)
const double ENGAGE_SCAN_DISTANCE_FACTOR=0.1; // influences the engage scan/stepping distance
bool ResolveLinkPath(const IntPoint &startPoint, const IntPoint &endPoint, ClearedArea &clearedArea, Path &output);
const double CLEAN_PATH_TOLERANCE = 0.5;
const double FINISHING_CLEAN_PATH_TOLERANCE = 0.1;
friend class EngagePoint; // for CalcCutArea
// used for filtering out of insignificant cuts:
const double MIN_CUT_AREA_FACTOR = 0.1; // influences filtering of cuts that with cumulative area below threshold, reasonable value is between 0.1 and 1
void CheckReportProgress(TPaths &progressPaths, bool force = false);
void AddPathsToProgress(TPaths &progressPaths, const Paths paths, MotionType mt = MotionType::mtCutting);
void AddPathToProgress(TPaths &progressPaths, const Path pth, MotionType mt = MotionType::mtCutting);
void ApplyStockToLeave(Paths &inputPaths);
const long PASSES_LIMIT = __LONG_MAX__; // limit used while debugging
const long POINTS_PER_PASS_LIMIT = __LONG_MAX__; // limit used while debugging
const time_t PROGRESS_TICKS = CLOCKS_PER_SEC/20; // progress report interval
private: // constants for fine tuning
const double RESOLUTION_FACTOR = 8.0;
const int MAX_ITERATIONS = 16;
const double AREA_ERROR_FACTOR = 0.05; /* how precise to match the cut area to optimal, reasonable value: 0.05 = 5%*/
const size_t ANGLE_HISTORY_POINTS = 3; // used for angle prediction
const int DIRECTION_SMOOTHING_BUFLEN = 3; // gyro points - used for angle smoothing
const double ENGAGE_AREA_THR_FACTOR = 0.2; // influences minimal engage area (factor relation to optimal)
const double ENGAGE_SCAN_DISTANCE_FACTOR = 0.5; // influences the engage scan/stepping distance
};
}
const double CLEAN_PATH_TOLERANCE = 0.5;
const double FINISHING_CLEAN_PATH_TOLERANCE = 0.1;
// used for filtering out of insignificant cuts:
const double MIN_CUT_AREA_FACTOR = 0.1; // influences filtering of cuts that with cumulative area below threshold, reasonable value is between 0.1 and 1
const long PASSES_LIMIT = __LONG_MAX__; // limit used while debugging
const long POINTS_PER_PASS_LIMIT = __LONG_MAX__; // limit used while debugging
const time_t PROGRESS_TICKS = CLOCKS_PER_SEC / 10; // progress report interval
};
} // namespace AdaptivePath
#endif