diff --git a/src/Mod/Path/App/Area.cpp b/src/Mod/Path/App/Area.cpp index 07bcda2a7..1797f8473 100644 --- a/src/Mod/Path/App/Area.cpp +++ b/src/Mod/Path/App/Area.cpp @@ -729,7 +729,10 @@ void Area::build() { return; } +#ifdef AREA_TRACE_ENABLE TIME_INIT(t); +#endif + getPlane(); try { @@ -806,7 +809,7 @@ void Area::build() { myArea = std::move(area.myArea); } - TIME_PRINT(t,"prepare"); + TIME_TRACE(t,"prepare"); }catch(...) { clean(); @@ -1283,7 +1286,7 @@ TopoDS_Shape Area::toShape(const CArea &area, bool fill, const gp_Trsf *trsf) { } struct WireInfo { - TopoDS_Shape wire; + TopoDS_Wire wire; gp_Pnt pend; gp_Pnt pstart; }; @@ -1296,15 +1299,14 @@ struct GetWires { void operator()(const TopoDS_Shape &shape, int type) { WireInfo info; if(type == TopAbs_WIRE) - info.wire = shape; + info.wire = TopoDS::Wire(shape); else info.wire = BRepBuilderAPI_MakeWire(TopoDS::Edge(shape)).Wire(); - BRepTools_WireExplorer xp(TopoDS::Wire(shape)); + BRepTools_WireExplorer xp(info.wire); info.pstart = BRep_Tool::Pnt(xp.CurrentVertex()); for(;xp.More();xp.Next()); info.pend = BRep_Tool::Pnt(xp.CurrentVertex()); - info.wire = shape; wires.push_back(info); } }; @@ -1349,18 +1351,16 @@ struct ShapeInfo{ BRepExtrema_DistShapeShape extss(v,wire); if(extss.IsDone() && extss.NbSolution()) { d = extss.Value(); - p = extss.PointOnShape2(0); - support = extss.SupportOnShape2(0); - support_edge = extss.SupportTypeShape2(0)==BRepExtrema_IsOnEdge; + p = extss.PointOnShape2(1); + support = extss.SupportOnShape2(1); + support_edge = extss.SupportTypeShape2(1)==BRepExtrema_IsOnEdge; done = true; }else AREA_WARN("BRepExtrema_DistShapeShape failed"); } if(!done){ - double d1 = p.Distance(it->pstart); - double d2 = p.Distance(it->pend); - AREA_TRACE("start "<pstart)<<", " << d1 << - AREA_PT(it->pend)<<", " <pstart); + double d2 = pt.Distance(it->pend); if(d1pstart; @@ -1388,24 +1388,31 @@ struct ShapeInfo{ //Assumes nearest() has been called. Rebased the best wire //to begin with the best point. Currently only works with closed wire - TopoDS_Shape rebaseWire(gp_Pnt &pend) { + TopoDS_Shape rebaseWire(gp_Pnt &pend, double min_dist) { + AREA_TRACE("rebase wire"); BRepBuilderAPI_MakeWire mkWire; TopoDS_Shape estart; TopoDS_Edge eend; + + if(min_dist < Precision::Confusion()) + min_dist = Precision::Confusion(); + for(int state=0;state<3;++state) { BRepTools_WireExplorer xp(TopoDS::Wire(myBestWire->wire)); pend = BRep_Tool::Pnt(xp.CurrentVertex()); //checking the case of bestpoint == wire start if(state==0 && !mySupportEdge && pend.Distance(myBestPt)pend; return myBestWire->wire; } gp_Pnt pt; for(;xp.More();xp.Next(),pend=pt) { - //state==2 means we are in second pass. estart marks the new start of the wire - if(state==2 && estart.IsSame(xp.Current())) + //state==2 means we are in second pass. estart marks the new start of the wire. + //so seeing estart means we're done + if(state==2 && estart.IsEqual(xp.Current())) break; BRepAdaptor_Curve curve(xp.Current()); @@ -1421,12 +1428,50 @@ struct ShapeInfo{ if(mySupportEdge) { //if best point is on some edge, break the edge in half if(xp.Current().IsEqual(mySupport)) { - estart = mySupport; - state = 1; - eend = BRepBuilderAPI_MakeEdge(curve.Curve().Curve(), pend, myBestPt); - mkWire.Add(BRepBuilderAPI_MakeEdge(curve.Curve().Curve(), myBestPt, pt)); + double d1 = pend.Distance(myBestPt); + double d2 = pt.Distance(myBestPt); + + if(d1>min_dist && d2>min_dist) { + BRepBuilderAPI_MakeEdge mkEdge1,mkEdge2; + if(reversed) { + mkEdge1.Init(curve.Curve().Curve(), myBestPt, myBestPt); + mkEdge2.Init(curve.Curve().Curve(), pt, myBestPt); + }else{ + mkEdge1.Init(curve.Curve().Curve(), pend, myBestPt); + mkEdge2.Init(curve.Curve().Curve(), myBestPt, pt); + } + if(mkEdge1.IsDone() && mkEdge2.IsDone()) { + if(reversed) { + eend = TopoDS::Edge(mkEdge1.Edge().Reversed()); + mkWire.Add(TopoDS::Edge(mkEdge2.Edge().Reversed())); + }else{ + eend = mkEdge1.Edge(); + mkWire.Add(mkEdge2.Edge()); + } + estart = mySupport; + state = 1; + AREA_TRACE("edge broken "<start"); + estart = xp.Current(); + state = 1; + mkWire.Add(xp.Current()); + }else{ + AREA_TRACE("break edge->end"); + mySupportEdge = false; + myBestPt = pt; + continue; + } } }else if(myBestPt.Distance(pend)wire; } - std::list sortWires(gp_Pnt &pend) { + std::list sortWires3D(gp_Pnt &pend,double min_dist) { std::list wires; while(true) { AREA_TRACE("3D sort pt " << AREA_PT(myBestPt)); if(myRebase) { AREA_TRACE("3D sort rebase"); - wires.push_back(rebaseWire(pend)); + pend = myBestPt; + wires.push_back(rebaseWire(pend,min_dist)); }else if(!myStart){ AREA_TRACE("3D sort reverse"); wires.push_back(myBestWire->wire.Reversed()); @@ -1619,7 +1665,7 @@ std::list Area::sortWires(const std::list &shapes, 0,-1,&pstart,&pend, PARAM_FIELDS(PARAM_FARG,AREA_PARAMS_SORT))); AREA_TIME_2D5; }else{ - wires.splice(wires.end(),best_it->sortWires(pend)); + wires.splice(wires.end(),best_it->sortWires3D(pend,min_dist)); AREA_TIME_3D; } pstart = pend; diff --git a/src/Mod/Path/App/Area.h b/src/Mod/Path/App/Area.h index 9db1cc2bc..2955d7cb2 100644 --- a/src/Mod/Path/App/Area.h +++ b/src/Mod/Path/App/Area.h @@ -51,7 +51,7 @@ #define AREA_PT(_pt) '('<<(_pt).X()<<", " << (_pt).Y()<<", " << (_pt).Z()<<')' #define AREA_PT2(_pt) '('<<(_pt).x<<", " << (_pt).y<<')' #ifdef AREA_TRACE_ENABLE -# define AREA_TRACE AREA_LOG +# define AREA_TRACE(_msg) AREA_LOG('('<<__LINE__<<"): " <<_msg) #else # define AREA_TRACE(...) do{}while(0) #endif @@ -69,12 +69,17 @@ #define TIME_INIT2(_t1,_t2) TIME_INIT(_t1),_t2=_t1 #define TIME_INIT3(_t1,_t2,_t3) TIME_INIT(_t1),_t2=_t1,_t3=_t1 -#define DURATION_PRINT(_d,_msg) \ - AREA_LOG(_msg<< " time: " << _d.count()<<'s'); +#define _DURATION_PRINT(_l,_d,_msg) \ + AREA_##_l(_msg<< " time: " << _d.count()<<'s'); + +#define DURATION_PRINT(_d,_msg) _DURATION_PRINT(LOG,_d,_msg) #define TIME_PRINT(_t,_msg) \ DURATION_PRINT(Path::getDuration(_t),_msg); +#define TIME_TRACE(_t,_msg) \ + _DURATION_PRINT(TRACE,Path::getDuration(_t),_msg); + #define DURATION_INIT(_d) \ std::chrono::TIME_UNIT _d(0)