diff --git a/src/Mod/Path/App/Area.cpp b/src/Mod/Path/App/Area.cpp index c60bcc0f9e..51d2bbd924 100644 --- a/src/Mod/Path/App/Area.cpp +++ b/src/Mod/Path/App/Area.cpp @@ -1380,7 +1380,7 @@ void Area::build() { } } -TopoDS_Shape Area::toShape(CArea &area, short fill) { +TopoDS_Shape Area::toShape(CArea &area, short fill, int reorient) { gp_Trsf trsf(myTrsf.Inverted()); bool bFill; switch(fill){ @@ -1397,11 +1397,11 @@ TopoDS_Shape Area::toShape(CArea &area, short fill) { if(&area == myArea.get()) { CArea copy(area); copy.FitArcs(); - return toShape(copy,bFill,&trsf); + return toShape(copy,bFill,&trsf,reorient); } area.FitArcs(); } - return toShape(area,bFill,&trsf); + return toShape(area,bFill,&trsf,reorient); } @@ -1515,9 +1515,9 @@ TopoDS_Shape Area::getShape(int index) { return myShape; } -TopoDS_Shape Area::makeOffset(int index,PARAM_ARGS(PARAM_FARG,AREA_PARAMS_OFFSET)) { +TopoDS_Shape Area::makeOffset(int index,PARAM_ARGS(PARAM_FARG,AREA_PARAMS_OFFSET),int reorient) { build(); - AREA_SECTION(makeOffset,index,PARAM_FIELDS(PARAM_FARG,AREA_PARAMS_OFFSET)); + AREA_SECTION(makeOffset,index,PARAM_FIELDS(PARAM_FARG,AREA_PARAMS_OFFSET),reorient); std::list > areas; makeOffset(areas,PARAM_FIELDS(PARAM_FARG,AREA_PARAMS_OFFSET)); @@ -1527,7 +1527,7 @@ TopoDS_Shape Area::makeOffset(int index,PARAM_ARGS(PARAM_FARG,AREA_PARAMS_OFFSET TIME_INIT(t); area.Thicken(myParams.ToolRadius); TIME_PRINT(t,"Thicken"); - return toShape(area,FillFace); + return toShape(area,FillFace,reorient); } return TopoDS_Shape(); } @@ -1536,9 +1536,12 @@ TopoDS_Shape Area::makeOffset(int index,PARAM_ARGS(PARAM_FARG,AREA_PARAMS_OFFSET builder.MakeCompound(compound); TIME_INIT(t); DURATION_INIT(d); + + bool thicken = myParams.Thicken && myParams.ToolRadius>Precision::Confusion(); + for(shared_ptr area : areas) { short fill; - if(myParams.Thicken && myParams.ToolRadius>Precision::Confusion()) { + if(thicken){ area->Thicken(myParams.ToolRadius); DURATION_PLUS(d,t); fill = FillFace; @@ -1546,11 +1549,11 @@ TopoDS_Shape Area::makeOffset(int index,PARAM_ARGS(PARAM_FARG,AREA_PARAMS_OFFSET fill = myParams.Fill; else fill = FillNone; - const TopoDS_Shape &shape = toShape(*area,fill); + const TopoDS_Shape &shape = toShape(*area,fill,reorient); if(shape.IsNull()) continue; builder.Add(compound,shape); } - if(myParams.Thicken && myParams.ToolRadius>Precision::Confusion()) + if(thicken) DURATION_PRINT(d,"Thicken"); for(TopExp_Explorer it(compound,TopAbs_EDGE);it.More();) return compound; @@ -1686,7 +1689,8 @@ TopoDS_Shape Area::makePocket(int index, PARAM_ARGS(PARAM_FARG,AREA_PARAMS_POCKE Offset = -tool_radius-extra_offset-shift; ExtraPass = -1; Stepover = -stepover; - return makeOffset(index,PARAM_FIELDS(PARAM_FNAME,AREA_PARAMS_OFFSET)); + // make offset and make sure the loop is CW (i.e. inner wires) + return makeOffset(index,PARAM_FIELDS(PARAM_FNAME,AREA_PARAMS_OFFSET),-1); }case Area::PocketModeZigZagOffset: pm = ZigZagThenSingleOffsetPocketMode; break; @@ -1767,8 +1771,22 @@ static inline bool IsLeft(const gp_Pnt &a, const gp_Pnt &b, const gp_Pnt &c) { return ((b.X() - a.X())*(c.Y() - a.Y()) - (b.Y() - a.Y())*(c.X() - a.X())) > 0; } -TopoDS_Wire Area::toShape(const CCurve &c, const gp_Trsf *trsf) { +TopoDS_Wire Area::toShape(const CCurve &_c, const gp_Trsf *trsf, int reorient) { BRepBuilderAPI_MakeWire mkWire; + + CCurve cReversed; + if(reorient) { + if(_c.IsClosed() && + ((reorient>0 && _c.IsClockwise()) || + (reorient<0 && !_c.IsClockwise()))) + { + cReversed = _c; + cReversed.Reverse(); + }else + reorient = 0; + } + const CCurve &c = reorient?cReversed:_c; + gp_Pnt pstart,pt; bool first = true; for(const CVertex &v : c.m_vertices){ @@ -1830,13 +1848,13 @@ TopoDS_Wire Area::toShape(const CCurve &c, const gp_Trsf *trsf) { return mkWire.Wire(); } -TopoDS_Shape Area::toShape(const CArea &area, bool fill, const gp_Trsf *trsf) { +TopoDS_Shape Area::toShape(const CArea &area, bool fill, const gp_Trsf *trsf, int reorient) { BRep_Builder builder; TopoDS_Compound compound; builder.MakeCompound(compound); for(const CCurve &c : area.m_curves) { - const TopoDS_Wire &wire = toShape(c,trsf); + const TopoDS_Wire &wire = toShape(c,trsf,reorient); if(!wire.IsNull()) builder.Add(compound,wire); } diff --git a/src/Mod/Path/App/Area.h b/src/Mod/Path/App/Area.h index c020deb789..938df1ba76 100644 --- a/src/Mod/Path/App/Area.h +++ b/src/Mod/Path/App/Area.h @@ -227,7 +227,7 @@ protected: void addToBuild(CArea &area, const TopoDS_Shape &shape); /** Called internally to obtain the combained children shapes */ - TopoDS_Shape toShape(CArea &area, short fill); + TopoDS_Shape toShape(CArea &area, short fill, int reorient=0); /** Obtain a list of offseted areas * @@ -299,7 +299,7 @@ public: * If more than one offset is requested, a compound shape is return * containing all offset shapes as wires regardless of \c Fill setting. */ - TopoDS_Shape makeOffset(int index=-1, PARAM_ARGS_DEF(PARAM_FARG,AREA_PARAMS_OFFSET)); + TopoDS_Shape makeOffset(int index=-1, PARAM_ARGS_DEF(PARAM_FARG,AREA_PARAMS_OFFSET), int reoirent=0); /** Make a pocket of the combined shape * @@ -401,7 +401,7 @@ public: * its original position. * */ static TopoDS_Shape toShape(const CArea &area, bool fill, - const gp_Trsf *trsf=NULL); + const gp_Trsf *trsf=NULL, int reoirent=0); /** Convert a single curve into an OCC wire * @@ -409,7 +409,7 @@ public: * \arg \c trsf: optional transform matrix to transform the shape back into * its original position. * */ - static TopoDS_Wire toShape(const CCurve &curve, const gp_Trsf *trsf=NULL); + static TopoDS_Wire toShape(const CCurve &curve, const gp_Trsf *trsf=NULL, int reorient=0); /** Check if two OCC shape is coplanar */ static bool isCoplanar(const TopoDS_Shape &s1, const TopoDS_Shape &s2);