diff --git a/src/Mod/Path/App/Area.cpp b/src/Mod/Path/App/Area.cpp index e5504d6f60..8b917e7e2e 100644 --- a/src/Mod/Path/App/Area.cpp +++ b/src/Mod/Path/App/Area.cpp @@ -434,6 +434,19 @@ void Area::addToBuild(CArea &area, const TopoDS_Shape &shape) { } } +static inline void getEndPoints(const TopoDS_Edge &e, gp_Pnt &p1, gp_Pnt &p2) { + p1 = BRep_Tool::Pnt(TopExp::FirstVertex(e)); + p2 = BRep_Tool::Pnt(TopExp::LastVertex(e)); +} + +static inline void getEndPoints(const TopoDS_Wire &wire, gp_Pnt &p1, gp_Pnt &p2) { + BRepTools_WireExplorer xp(wire); + p1 = BRep_Tool::Pnt(TopoDS::Vertex(xp.CurrentVertex())); + for(;xp.More();xp.Next()); + p2 = BRep_Tool::Pnt(TopoDS::Vertex(xp.CurrentVertex())); +} + + struct WireJoiner { typedef bg::model::box Box; @@ -453,15 +466,6 @@ struct WireJoiner { return true; } - static void getEndPoints(const TopoDS_Edge &e, gp_Pnt &p1, gp_Pnt &p2) { - p1 = BRep_Tool::Pnt(TopExp::FirstVertex((e))); - p2 = BRep_Tool::Pnt(TopExp::LastVertex((e))); - // TopExp_Explorer xp(e,TopAbs_VERTEX); - // p1 = BRep_Tool::Pnt(TopoDS::Vertex(xp.Current())); - // xp.Next(); - // p2 = BRep_Tool::Pnt(TopoDS::Vertex(xp.Current())); - } - struct EdgeInfo { TopoDS_Edge edge; gp_Pnt p1; @@ -1780,6 +1784,7 @@ struct ShapeParams { double abscissa; int k; short orientation; + short direction; #ifdef AREA_TIME_ENABLE TIME_DURATION qd; //rtree query duration TIME_DURATION bd; //rtree build duration @@ -1787,8 +1792,8 @@ struct ShapeParams { TIME_DURATION xd; //BRepExtrema_DistShapeShape duration #endif - ShapeParams(double _a, int _k, short o) - :abscissa(_a),k(_k),orientation(o) + ShapeParams(double _a, int _k, short o, short d) + :abscissa(_a),k(_k),orientation(o),direction(d) #ifdef AREA_TIME_ENABLE ,qd(0),bd(0),rd(0),xd(0) #endif @@ -1824,18 +1829,46 @@ struct GetWires { } TIME_INIT(t); - BRepTools_WireExplorer xp(info.wire); if(params.abscissap2.X(); + break; + case Area::DirectionXNegative: + reverse = p1.X()p2.Y(); + break; + case Area::DirectionYNegative: + reverse = p1.Y()p2.Z(); + break; + case Area::DirectionZNegative: + reverse = p1.Z()pstart()); - double d2 = pt.SquareDistance(it->pend()); - if(d1pstart(); is_start = true; }else{ - d = d2; - p = it->pend(); - is_start = false; + double d2 = pt.SquareDistance(it->pend()); + if(d1pstart(); + is_start = true; + }else{ + d = d2; + p = it->pend(); + is_start = false; + } } } if(!first && d>=best_d) continue; @@ -2049,9 +2088,9 @@ struct ShapeInfo{ pend = myBestPt; estart = mySupport; state = 1; - AREA_TRACE((reversed?"reversed ":"")<<"edge split "< &wires; short orientation; + short direction; - WireOrienter(std::list &ws, short o) - :wires(ws),orientation(o) + WireOrienter(std::list &ws, short o, short d) + :wires(ws),orientation(o),direction(d) {} void operator()(const TopoDS_Shape &shape, int type) { @@ -2230,11 +2270,42 @@ struct WireOrienter { wires.push_back(shape); else wires.push_back(BRepBuilderAPI_MakeWire(TopoDS::Edge(shape)).Wire()); - if(orientation!=Area::OrientationNone && BRep_Tool::IsClosed(wires.back())) { - int dir = Area::getWireDirection(wires.back()); - if((dir>0&&orientation==Area::OrientationCW) || - (dir<0&&orientation==Area::OrientationCCW)) - wires.back().Reverse(); + + TopoDS_Shape &wire = wires.back(); + + if(BRep_Tool::IsClosed(wire)) { + if(orientation!=Area::OrientationNone) { + int dir = Area::getWireDirection(wire); + if((dir>0&&orientation==Area::OrientationCW) || + (dir<0&&orientation==Area::OrientationCCW)) + wire.Reverse(); + } + }else if(direction!=Area::DirectionNone) { + gp_Pnt p1,p2; + getEndPoints(TopoDS::Wire(wire),p1,p2); + bool reverse = false; + switch(direction) { + case Area::DirectionXPositive: + reverse = p1.X()>p2.X(); + break; + case Area::DirectionXNegative: + reverse = p1.X()p2.Y(); + break; + case Area::DirectionYNegative: + reverse = p1.Y()p2.Z(); + break; + case Area::DirectionZNegative: + reverse = p1.Z() Area::sortWires(const std::list &shapes, for(auto &shape : shapes) { if(!shape.IsNull()) foreachSubshape(shape, - WireOrienter(wires,orientation), TopAbs_WIRE); + WireOrienter(wires,orientation,direction), TopAbs_WIRE); } return std::move(wires); } - ShapeParams rparams(abscissa,nearest_k>0?nearest_k:1,orientation); + ShapeParams rparams(abscissa,nearest_k>0?nearest_k:1,orientation,direction); std::list shape_list; TIME_INIT2(t,t1); diff --git a/src/Mod/Path/App/AreaParams.h b/src/Mod/Path/App/AreaParams.h index 8c5a78edf4..8e2f836c68 100644 --- a/src/Mod/Path/App/AreaParams.h +++ b/src/Mod/Path/App/AreaParams.h @@ -199,7 +199,9 @@ ((short, nearest_k, NearestK, 3, "Nearest k sampling vertices are considered during sorting"))\ ((enum, orientation, Orientation, 0, "Enforce loop orientation\n"\ "Note the CW/CCW here specifies the outer wire orientation. For inner wires (holes), the\n"\ - "enforced orientation is reversed", (None)(CW)(CCW))) + "enforced orientation is reversed", (None)(CW)(CCW)))\ + ((enum, direction, Direction, 0, "Enforce open path direction",\ + (None)(XPositive)(XNegative)(YPositive)(YNegative)(ZPositive)(ZNegative))) /** Area path generation parameters */ #define AREA_PARAMS_PATH \