Path.Area: change fromShape() 'start' parameter behavior

'start' used to mean the initial resting position of the tool. Now it
is changed to mean the feed start position.

fromShape() has also improved to automatically guess 'retraction' and
'resume_height' parameters if not given, based on input shape boundary.
This commit is contained in:
Zheng, Lei
2017-07-04 10:37:12 +08:00
parent 00b0027e19
commit 4b2a739e7a
4 changed files with 111 additions and 41 deletions

View File

@@ -122,7 +122,7 @@ public:
"fromShapes(shapes, start=Vector(), return_end=False" PARAM_PY_ARGS_DOC(ARG,AREA_PARAMS_PATH) ")\n"
"\nReturns a Path object from a list of shapes\n"
"\n* shapes: input list of shapes.\n"
"\n* start (Vector()): optional start position.\n"
"\n* start (Vector()): feed start position, and also serves as a hint of path entry.\n"
"\n* return_end (False): if True, returns tuple (path, endPosition).\n"
PARAM_PY_DOC(ARG, AREA_PARAMS_PATH)
);
@@ -415,7 +415,7 @@ private:
try {
bool need_arc_plane = arc_plane==Area::ArcPlaneAuto;
std::list<TopoDS_Shape> wires = Area::sortWires(shapes,&pstart,
&pend, &arc_plane, PARAM_PY_FIELDS(PARAM_FARG,AREA_PARAMS_SORT));
&pend, 0, &arc_plane, PARAM_PY_FIELDS(PARAM_FARG,AREA_PARAMS_SORT));
PyObject *list = PyList_New(0);
for(auto &wire : wires)
PyList_Append(list,Py::new_reference_to(

View File

@@ -2435,11 +2435,13 @@ struct ShapeInfo{
return myBestWire->wire;
}
std::list<TopoDS_Shape> sortWires(const gp_Pnt &pstart, gp_Pnt &pend,double min_dist) {
std::list<TopoDS_Shape> sortWires(const gp_Pnt &pstart, gp_Pnt &pend,double min_dist, gp_Pnt *pentry) {
if(pstart.SquareDistance(myStartPt)>Precision::SquareConfusion())
nearest(pstart);
if(pentry) *pentry = myBestPt;
std::list<TopoDS_Shape> wires;
if(min_dist < 0.01)
min_dist = 0.01;
@@ -2607,7 +2609,7 @@ struct WireOrienter {
};
std::list<TopoDS_Shape> Area::sortWires(const std::list<TopoDS_Shape> &shapes,
const gp_Pnt *_pstart, gp_Pnt *_pend, short *_parc_plane,
gp_Pnt *_pstart, gp_Pnt *_pend, double *stepdown_hint, short *_parc_plane,
PARAM_ARGS(PARAM_FARG,AREA_PARAMS_SORT))
{
std::list<TopoDS_Shape> wires;
@@ -2732,7 +2734,12 @@ std::list<TopoDS_Shape> Area::sortWires(const std::list<TopoDS_Shape> &shapes,
AREA_TRACE("bound (" << xMin<<", "<<xMax<<"), ("<<
yMin<<", "<<yMax<<"), ("<<zMin<<", "<<zMax<<')');
pstart.SetCoord(xMax,yMax,zMax);
if(_pstart) *_pstart = pstart;
}
gp_Pln pln;
double hint = 0.0;
bool hint_first = true;
while(shape_list.size()) {
AREA_TRACE("sorting " << shape_list.size() << ' ' << AREA_XYZ(pstart));
double best_d;
@@ -2751,10 +2758,42 @@ std::list<TopoDS_Shape> Area::sortWires(const std::list<TopoDS_Shape> &shapes,
best_d = d;
}
}
wires.splice(wires.end(),best_it->sortWires(pstart,pend,min_dist));
gp_Pnt pentry;
wires.splice(wires.end(),best_it->sortWires(pstart,pend,min_dist,&pentry));
if(use_bound && _pstart) {
use_bound = false;
*_pstart = pentry;
}
if(sort_mode==SortMode2D5 && stepdown_hint) {
if(!best_it->myPlanar)
hint_first = true;
else if(hint_first)
hint_first = false;
else{
// Calculate distance of two gp_pln.
//
// Can't use gp_pln.Distance(), because it only calculate
// the distance if two plane are parallel. And it checks
// parallelity using tolerance gp::Resolution() which is
// defined as DBL_MIN (min double) in Standard_Real.hxx.
// Really? Is that a bug?
const gp_Pnt& P = pln.Position().Location();
const gp_Pnt& loc = best_it->myPln.Position().Location ();
const gp_Dir& dir = best_it->myPln.Position().Direction();
double d = (dir.X() * (P.X() - loc.X()) +
dir.Y() * (P.Y() - loc.Y()) +
dir.Z() * (P.Z() - loc.Z()));
if (d < 0) d = -d;
if(d>hint)
hint = d;
}
pln = best_it->myPln;
}
pstart = pend;
shape_list.erase(best_it);
}
if(stepdown_hint && hint!=0.0)
*stepdown_hint = hint;
if(_pend) *_pend = pend;
FC_DURATION_LOG(rparams.bd,"rtree build");
FC_DURATION_LOG(rparams.qd,"rtree query");
@@ -2805,24 +2844,22 @@ static void addG0(bool verbose, Toolpath &path,
double retraction, double resume_height,
double f, double &last_f)
{
if(!getter || retraction-(last.*getter)() < Precision::Confusion()) {
addGCode(verbose,path,last,next,"G0");
return;
}
gp_Pnt pt(last);
(pt.*setter)(retraction);
addGCode(verbose,path,last,pt,"G0");
last = pt;
pt = next;
(pt.*setter)(retraction);
addGCode(verbose,path,last,pt,"G0");
if(resume_height>Precision::Confusion() &&
resume_height+(next.*getter)() < retraction)
{
if(retraction-(last.*getter)() > Precision::Confusion()) {
(pt.*setter)(retraction);
addGCode(verbose,path,last,pt,"G0");
last = pt;
pt = next;
(pt.*setter)((next.*getter)()+resume_height);
(pt.*setter)(retraction);
addGCode(verbose,path,last,pt,"G0");
}
if(resume_height>Precision::Confusion()) {
if(resume_height+(next.*getter)() < retraction) {
last = pt;
pt = next;
(pt.*setter)((next.*getter)()+resume_height);
addGCode(verbose,path,last,pt,"G0");
}
addG1(verbose,path,pt,next,f,last_f);
}else
addGCode(verbose,path,pt,next,"G0");
@@ -2880,11 +2917,15 @@ void Area::setWireOrientation(TopoDS_Wire &wire, const gp_Dir &dir, bool wire_cc
}
void Area::toPath(Toolpath &path, const std::list<TopoDS_Shape> &shapes,
const gp_Pnt *pstart, gp_Pnt *pend, PARAM_ARGS(PARAM_FARG,AREA_PARAMS_PATH))
const gp_Pnt *_pstart, gp_Pnt *pend, PARAM_ARGS(PARAM_FARG,AREA_PARAMS_PATH))
{
std::list<TopoDS_Shape> wires;
wires = sortWires(shapes,pstart,pend,
gp_Pnt pstart;
if(_pstart) pstart = *_pstart;
double stepdown_hint = 1.0;
wires = sortWires(shapes,&pstart,pend,&stepdown_hint,
PARAM_REF(PARAM_FARG,AREA_PARAMS_ARC_PLANE),
PARAM_FIELDS(PARAM_FARG,AREA_PARAMS_SORT));
@@ -2903,30 +2944,57 @@ void Area::toPath(Toolpath &path, const std::list<TopoDS_Shape> &shapes,
addGCode(path,"G17");
}
AxisGetter getter;
AxisSetter setter;
switch(retract_axis) {
case RetractAxisX:
getter = &gp_Pnt::X;
setter = &gp_Pnt::SetX;
break;
case RetractAxisY:
getter = &gp_Pnt::Y;
setter = &gp_Pnt::SetY;
break;
default:
getter = &gp_Pnt::Z;
setter = &gp_Pnt::SetZ;
}
threshold = fabs(threshold);
if(threshold < Precision::Confusion())
threshold = Precision::Confusion();
threshold *= threshold;
resume_height = fabs(resume_height);
AxisGetter getter = &gp_Pnt::Z;
AxisSetter setter = &gp_Pnt::SetZ;
resume_height = fabs(resume_height);
if(resume_height < Precision::Confusion())
resume_height = stepdown_hint;
retraction = fabs(retraction);
if(retraction>Precision::Confusion()) {
switch(retract_axis) {
case RetractAxisX:
getter = &gp_Pnt::X;
setter = &gp_Pnt::SetX;
break;
case RetractAxisY:
getter = &gp_Pnt::Y;
setter = &gp_Pnt::SetY;
break;
}
}
if(retraction < Precision::Confusion())
retraction = (pstart.*getter)()+resume_height;
// in case the user didn't specify feed start, sortWire() will choose one
// based on the bound. We'll further adjust that according to resume height
if(!_pstart || pstart.SquareDistance(*_pstart)>Precision::SquareConfusion())
(pstart.*setter)((pstart.*getter)()+resume_height);
gp_Pnt plast,p;
if(pstart) plast = *pstart;
// initial vertial rapid pull up to retraction (or start Z height if higher)
(p.*setter)(std::max(retraction,(pstart.*getter)()));
addGCode(false,path,plast,p,"G0");
plast = p;
p = pstart;
// rapid horizontal move if start Z is below retraction
if(fabs((p.*getter)()-retraction) > Precision::Confusion()) {
(p.*setter)(retraction);
addGCode(false,path,plast,p,"G0");
plast = p;
p = pstart;
}
// vertial rapid down to feed start
addGCode(false,path,plast,p,"G0");
plast = p;
bool first = true;
bool arcWarned = false;
double cur_f = 0.0; // current feed rate
@@ -2947,7 +3015,7 @@ void Area::toPath(Toolpath &path, const std::list<TopoDS_Shape> &shapes,
(pTmp.*setter)(0.0);
(plastTmp.*setter)(0.0);
if(first||pTmp.SquareDistance(plastTmp)>threshold)
if(!first && pTmp.SquareDistance(plastTmp)>threshold)
addG0(verbose,path,plast,p,getter,setter,retraction,resume_height,vf,cur_f);
else
addG1(verbose,path,plast,p,vf,cur_f);

View File

@@ -341,6 +341,8 @@ public:
* \arg \c shapes: input list of shapes.
* \arg \c pstart: optional start point
* \arg \c pend: optional output containing the ending point of the returned
* \arg \c stepdown_hint: optional output of a hint of step down as the max
* distance between two sections.
* \arg \c arc_plane: optional arc plane selection, if given the found plane
* will be returned. See #AREA_PARAMS_ARC_PLANE for more details.
*
@@ -349,8 +351,8 @@ public:
* \return sorted wires
*/
static std::list<TopoDS_Shape> sortWires(const std::list<TopoDS_Shape> &shapes,
const gp_Pnt *pstart=NULL, gp_Pnt *pend=NULL, short *arc_plane = NULL,
PARAM_ARGS_DEF(PARAM_FARG,AREA_PARAMS_SORT));
gp_Pnt *pstart=NULL, gp_Pnt *pend=NULL, double *stepdown_hint=NULL,
short *arc_plane = NULL, PARAM_ARGS_DEF(PARAM_FARG,AREA_PARAMS_SORT));
/** Convert a list of wires to gcode
*

View File

@@ -55,7 +55,7 @@ PARAM_ENUM_STRING_DECLARE(static const char *Enums,AREA_PARAMS_PATH)
FeatureShape::FeatureShape()
{
ADD_PROPERTY(Sources,(0));
ADD_PROPERTY_TYPE(StartPoint,(Base::Vector3d()),"Path",App::Prop_None,"Path start position");
ADD_PROPERTY_TYPE(StartPoint,(Base::Vector3d()),"Path",App::Prop_None,"Feed start position");
PARAM_PROP_ADD("Path",AREA_PARAMS_PATH);
PARAM_PROP_SET_ENUM(Enums,AREA_PARAMS_PATH);
}