Path: Adaptive - fix for edge selections

This commit is contained in:
kreso-t
2018-09-05 22:30:51 +02:00
committed by wmayer
parent f7ff42fe2b
commit 834a374f7b
3 changed files with 120 additions and 96 deletions

View File

@@ -16,75 +16,6 @@ def discretize(edge, flipDirection=False):
if flipDirection: pts.reverse()
return pts
def IsEqualInXYPlane(e1, e2):
return math.sqrt((e2.x-e1.x)*(e2.x-e1.x) +
(e2.y - e1.y) * (e2.y - e1.y))<0.01
def connectEdges(edges):
''' Makes the list of connected discretized paths '''
# find edge
lastPoint=None
remaining = []
pathArray = []
combined = []
for edge in edges:
#print edge
p1 = edge.valueAt(edge.FirstParameter)
p2 = edge.valueAt(edge.LastParameter)
m1 = edge.valueAt((edge.LastParameter+edge.LastParameter)/2)
duplicate = False
for ex in remaining:
exp1 = ex.valueAt(ex.FirstParameter)
exp2 = ex.valueAt(ex.LastParameter)
exm1 = ex.valueAt((ex.FirstParameter + ex.LastParameter)/2)
if IsEqualInXYPlane(exp1, p1) and IsEqualInXYPlane(exp2, p2) and IsEqualInXYPlane(exm1, m1):
duplicate = True
#print "duplicate"
if IsEqualInXYPlane(exp1, p2) and IsEqualInXYPlane(exp2, p1) and IsEqualInXYPlane(exm1, m1):
duplicate = True
#print "duplicate"
if not duplicate:
remaining.append(edge)
newPath=True
while len(remaining)>0:
if newPath:
edge=remaining[0]
p1 = edge.valueAt(edge.FirstParameter)
p2 = edge.valueAt(edge.LastParameter)
if len(combined)>0: pathArray.append(combined)
combined = []
combined.append(discretize(edge))
remaining.remove(edge)
lastPoint=p2
newPath=False
anyMatch=False
for e in remaining:
p1 = e.valueAt(e.FirstParameter)
p2 = e.valueAt(e.LastParameter)
if IsEqualInXYPlane(lastPoint,p1):
combined.append(discretize(e))
remaining.remove(e)
lastPoint=p2
anyMatch=True
break
elif IsEqualInXYPlane(lastPoint,p2):
combined.append(discretize(e,True))
remaining.remove(e)
lastPoint=p1
anyMatch=True
break
if not anyMatch:
newPath=True
#make sure last path is appended
if len(combined)>0: pathArray.append(combined)
combined = []
return pathArray
def convertTo2d(pathArray):
output = []
for path in pathArray:
@@ -267,14 +198,15 @@ def Execute(op,obj):
obj.StopProcessing = False
if obj.Tolerance<0.001: obj.Tolerance=0.001
edges=[]
pathArray=[]
for base, subs in obj.Base:
for sub in subs:
shape=base.Shape.getElement(sub)
for edge in shape.Edges:
edges.append(edge)
pathArray.append([discretize(edge)])
pathArray=connectEdges(edges)
#pathArray=connectEdges(edges)
path2d = convertTo2d(pathArray)
stockPaths = []
if op.stock.StockType == "CreateCylinder":
@@ -289,6 +221,8 @@ def Execute(op,obj):
v.append(FreeCAD.Vector(stockBB.XMin,stockBB.YMin,0))
stockPaths.append([v])
stockPath2d = convertTo2d(stockPaths)
opType = area.AdaptiveOperationType.ClearingInside
if obj.OperationType == "Clearing":
if obj.Side == "Outside":
@@ -301,8 +235,6 @@ def Execute(op,obj):
else:
opType = area.AdaptiveOperationType.ProfilingInside
path2d = convertTo2d(pathArray)
stockPath2d = convertTo2d(stockPaths)
# put here all properties that influence calculation of adaptive base paths,
inputStateObject = {
@@ -426,7 +358,7 @@ class PathAdaptive(PathOp.ObjectOp):
obj.StepOver = 20
obj.LiftDistance=0
# obj.ProcessHoles = True
obj.ForceInsideOut = True
obj.ForceInsideOut = False
obj.Stopped = False
obj.StopProcessing = False
obj.HelixAngle = 5

View File

@@ -13,7 +13,11 @@ namespace ClipperLib {
namespace AdaptivePath {
using namespace ClipperLib;
using namespace std;
#define SAME_POINT_TOL_SQRD_SCALED 16.0
/*********************************************
* Utils - inline
***********************************************/
inline double DistanceSqrd(const IntPoint& pt1, const IntPoint& pt2)
{
@@ -50,10 +54,8 @@ namespace AdaptivePath {
}
}
}
/*********************************************
* Utils
***********************************************/
/* inline util*/
inline bool HasAnyPath(const Paths &paths) {
for(Paths::size_type i=0;i<paths.size();i++) {
if(paths[i].size()>0) return true;
@@ -75,7 +77,6 @@ namespace AdaptivePath {
return DoublePoint(c*in.X-s*in.Y,s*in.X + c*in.Y);
}
// calculates path length for open path
inline double PathLength(const Path & path) {
double len=0;
@@ -86,7 +87,22 @@ namespace AdaptivePath {
return len;
}
/* geom utils */
inline double PointSideOfLine(const IntPoint& p1, const IntPoint& p2,const IntPoint& pt) {
return double((pt.X - p1.X)*(p2.Y-p1.Y) - (pt.Y - p2.Y)*(p2.X-p1.X));
}
inline double Angle3Points(const DoublePoint & p1,const DoublePoint& p2, const DoublePoint& p3) {
double t1= atan2(p1.Y-p2.Y,p1.X-p2.X);
double t2=atan2(p3.Y-p2.Y,p3.X-p2.X);
double a = fabs( t2 - t1 );
return min(a,2*M_PI-a);
}
/*********************************************
* Utils
***********************************************/
void AverageDirection(const vector<DoublePoint> &unityVectors, DoublePoint& output) {
int size=unityVectors.size();
output.X =0;
@@ -198,16 +214,6 @@ namespace AdaptivePath {
return true;
}
inline double PointSideOfLine(const IntPoint& p1, const IntPoint& p2,const IntPoint& pt) {
return double((pt.X - p1.X)*(p2.Y-p1.Y) - (pt.Y - p2.Y)*(p2.X-p1.X));
}
inline double Angle3Points(const DoublePoint & p1,const DoublePoint& p2, const DoublePoint& p3) {
double t1= atan2(p1.Y-p2.Y,p1.X-p2.X);
double t2=atan2(p3.Y-p2.Y,p3.X-p2.X);
double a = fabs( t2 - t1 );
return min(a,2*M_PI-a);
}
bool Line2CircleIntersect(const IntPoint &c, double radius,const IntPoint &p1, const IntPoint &p2, vector<DoublePoint> & result, bool clamp=true)
{
@@ -703,6 +709,87 @@ namespace AdaptivePath {
return true;
}
void DeduplicatePaths(const Paths & inputs,Paths & outputs) {
outputs.clear();
for(const auto & new_pth :inputs) {
bool duplicate=false;
// aff all points of new path exist on some of the old paths, path is considered duplicate
for(const auto & old_pth :outputs) {
bool all_points_exists=true;
for(const auto pt1:new_pth) {
bool pointExists=false;
for(const auto pt2:old_pth) {
if(DistanceSqrd(pt1,pt2)<SAME_POINT_TOL_SQRD_SCALED) {
pointExists=true;
break;
}
}
if(!pointExists) {
all_points_exists=false;
break;
}
}
if(all_points_exists) {
duplicate=true;
break;
}
}
if(!duplicate && new_pth.size()>0) {
outputs.push_back(new_pth);
}
}
}
void ConnectPaths(Paths input,Paths & output) {
// remove duplicate paths
output.clear();
bool newPath = true;
Path joined;
while(input.size()>0) {
if(newPath) {
auto p1=input.front().front();
auto p2=input.front().back();
if(joined.size()>0) output.push_back(joined);
joined.clear();
for(auto pt:input.front()) {
joined.push_back(pt);
}
input.erase(input.begin());
newPath=false;
}
bool anyMatch=false;
for(size_t i=0;i<input.size();i++) {
Path & n= input.at(i);
if(DistanceSqrd(n.front(),joined.back())<SAME_POINT_TOL_SQRD_SCALED) {
for(auto pt:n) joined.push_back(pt);
input.erase(input.begin()+i);
anyMatch=true;
break;
} else if(DistanceSqrd(n.back(),joined.back())<SAME_POINT_TOL_SQRD_SCALED) {
ReversePath(n);
for(auto pt:n) joined.push_back(pt);
input.erase(input.begin()+i);
anyMatch=true;
break;
} else if(DistanceSqrd(n.front(),joined.front())<SAME_POINT_TOL_SQRD_SCALED) {
for(auto pt:n) joined.insert(joined.begin(),pt);
input.erase(input.begin()+i);
anyMatch=true;
break;
} else if(DistanceSqrd(n.back(),joined.front())<SAME_POINT_TOL_SQRD_SCALED) {
ReversePath(n);
for(auto pt:n) joined.insert(joined.begin(),pt);
input.erase(input.begin()+i);
anyMatch=true;
break;
}
}
if(!anyMatch) newPath = true;
}
if(joined.size()>0) output.push_back(joined);
}
/****************************************
// Adaptive2d - constructor
*****************************************/
@@ -984,15 +1071,18 @@ namespace AdaptivePath {
// **********************
// Convert input paths to clipper
//************************
inputPaths.clear();
Paths converted;
for(size_t i=0;i<paths.size();i++) {
Path cpth;
for(size_t j=0;j<paths[i].size();j++) {
std::pair<double,double> pt = paths[i][j];
cpth.push_back(IntPoint(long(pt.first*scaleFactor),long(pt.second*scaleFactor)));
}
inputPaths.push_back(cpth);
}
converted.push_back(cpth);
}
DeduplicatePaths(converted,inputPaths);
ConnectPaths(inputPaths,inputPaths);
SimplifyPolygons(inputPaths);
//************************
@@ -1392,7 +1482,7 @@ namespace AdaptivePath {
output.AdaptivePaths.push_back(linkPath3);
linkFound=true;
}
if(!linkFound && keepDownLinkTooLong) { // if to long make link through interim points with tool raise
if(!linkFound && keepDownLinkTooLong) { // if keeptooldown link too long make link through interim points with tool raise
// add disengage moves
TPath linkPath1;
linkPath1.first = MotionType::mtCutting;
@@ -1441,7 +1531,7 @@ namespace AdaptivePath {
}
}
}
if(!linkFound) { // noting clear so far - check direct link with no interim points - either this is clear or we need to raise the tool
if(!linkFound) { // nothing clear so far - check direct link with no interim points - either this is clear or we need to raise the tool
//cerr << "keepToolDownLinkPath NOT CLEAR" << endl;
Path tp;
tp << lastPoint;

View File

@@ -130,6 +130,8 @@ namespace AdaptivePath {
const time_t PROGRESS_TICKS = CLOCKS_PER_SEC/20; // progress report interval
const long OVERSHOOT_ADDON_DIST=2;
};
}
#endif