diff --git a/src/Mod/Path/App/Area.cpp b/src/Mod/Path/App/Area.cpp index 8101ef21b0..6d360b3a36 100644 --- a/src/Mod/Path/App/Area.cpp +++ b/src/Mod/Path/App/Area.cpp @@ -332,7 +332,7 @@ int Area::addShape(CArea &area, const TopoDS_Shape &shape, const gp_Trsf *trsf, static std::vector discretize(const TopoDS_Edge &edge, double deflection) { std::vector ret; BRepAdaptor_Curve curve(edge); - Standard_Real efirst,elast,first,last; + Standard_Real efirst,elast; efirst = curve.FirstParameter(); elast = curve.LastParameter(); bool reversed = (edge.Orientation()==TopAbs_REVERSED); @@ -340,29 +340,12 @@ static std::vector discretize(const TopoDS_Edge &edge, double deflection // push the first point ret.push_back(curve.Value(reversed?elast:efirst)); - Handle(Geom_Curve) c = BRep_Tool::Curve(edge, first, last); - first = c->FirstParameter(); - last = c->LastParameter(); - if(efirst>elast) { - if(firstlast) - std::swap(first,last); - - // NOTE: OCCT QuasiUniformDeflection has a bug cause it to return only - // partial points for some (BSpline) curve if we pass in the edge trimmed - // first and last parameters. Passing the original curve first and last - // parameters works fine. The following algorithm uses the original curve - // parameters, and skip those out of range. The algorithm shall work the - // same for any other discetization algorithm, althgouth it seems only - // QuasiUniformDeflection has this bug. - // NOTE: QuasiUniformDeflection has trouble with some B-Spline, see // https://forum.freecadweb.org/viewtopic.php?f=15&t=42628 // // GCPnts_QuasiUniformDeflection discretizer(curve, deflection, first, last); // - GCPnts_UniformDeflection discretizer(curve, deflection, first, last); + GCPnts_UniformDeflection discretizer(curve, deflection, efirst, elast); if (!discretizer.IsDone ()) Standard_Failure::Raise("Curve discretization failed"); if(discretizer.NbPoints () > 1) { @@ -370,22 +353,10 @@ static std::vector discretize(const TopoDS_Edge &edge, double deflection //strangely OCC discretizer points are one-based, not zero-based, why? if(reversed) { for (int i=nbPoints-1; i>=1; --i) { - auto param = discretizer.Parameter(i); - if(firstelast) - continue; - }else if(param>efirst || paramelast) - continue; - }else if(param>efirst || param= 1.55"); #else - // It seems OCC projector sometimes mess up the tolerance of edges - // which are supposed to be connected. So use a lesser precision - // below, and call makeCleanWire to fix the tolerance - const double tol = 1e-10; + // Note on tolerance: It seems OCC projector sometimes mess up the + // tolerance of edges which are supposed to be connected. So use a + // lesser precision below, and call makeCleanWire to fix the tolerance std::vector adjacentList; std::set edgesToVisit; @@ -1185,7 +1155,7 @@ static int foreachSubshape(const TopoDS_Shape &shape, } if(openShapes.empty()) return res; - + BRep_Builder builder; TopoDS_Compound comp; builder.MakeCompound(comp); @@ -1258,7 +1228,9 @@ TopoDS_Shape Area::findPlane(const TopoDS_Shape &shape, gp_Trsf &trsf) } int Area::project(TopoDS_Shape &shape_out, - const TopoDS_Shape &shape_in, const AreaParams *params) + const TopoDS_Shape &shape_in, + const AreaParams *params, + const TopoDS_Shape *work_plane) { FC_TIME_INIT2(t,t1); Handle_HLRBRep_Algo brep_hlr = NULL; @@ -1309,7 +1281,8 @@ int Area::project(TopoDS_Shape &shape_out, showShape(v.edge,"split"); } - int skips = joiner.findClosedWires(); + double tolerance = params ? params->Tolerance : Precision::Confusion(); + int skips = joiner.findClosedWires(tolerance); FC_TIME_LOG(t1,"WireJoiner findClosedWires"); showShape(joiner.comp,"pre_project"); @@ -1325,6 +1298,9 @@ int Area::project(TopoDS_Shape &shape_out, area.myParams.Fill = TopExp_Explorer(shape_in,TopAbs_FACE).More()?FillFace:FillNone; area.myParams.Coplanar = CoplanarNone; area.myProjecting = true; + if (work_plane) { + area.myWorkPlane = *work_plane; + } area.add(joiner.comp, OperationUnion); const TopoDS_Shape &shape = area.getShape(); @@ -1627,7 +1603,8 @@ std::list Area::getProjectedShapes(const gp_Trsf &trsf, bool invers mySkippedShapes = 0; for(auto &s : myShapes) { TopoDS_Shape out; - int skipped = Area::project(out,s.shape.Moved(loc),&myParams); + int skipped = + Area::project(out, s.shape.Moved(loc), &myParams, &myWorkPlane); if(skipped < 0) { ++mySkippedShapes; continue; @@ -3300,7 +3277,7 @@ void Area::toPath(Toolpath &path, const std::list &shapes, (p.*setter)(retraction); addGCode(false,path,plast,p,"G0"); } - + plast = p; bool first = true; diff --git a/src/Mod/Path/App/Area.h b/src/Mod/Path/App/Area.h index 3e0c70f5f0..4a472bcba8 100644 --- a/src/Mod/Path/App/Area.h +++ b/src/Mod/Path/App/Area.h @@ -87,7 +87,7 @@ struct PathExport CAreaConfig { /** For saving current libarea settings */ PARAM_DECLARE(PARAM_FNAME,AREA_PARAMS_CAREA) - /** The constructor automatically saves current setting and apply user defined ones + /** The constructor automatically saves current setting and apply user defined ones * * \arg \c p user defined configurations * \arg \c noFitArgs if true, will override and disable arc fitting. Because @@ -176,13 +176,13 @@ public: bool isBuilt() const; - /** Set a working plane + /** Set a working plane * * \arg \c shape: a shape defining a working plane. * * The supplied shape does not need to be planar. Area will try to find planar - * sub-shape (face, wire or edge). If more than one planar sub-shape is found, - * it will prefer the top plane parallel to XY0 plane. + * sub-shape (face, wire or edge). If more than one planar sub-shape is found, + * it will prefer the top plane parallel to XY0 plane. * * If no working plane are set, Area will try to find a working plane from * the added children shape using the same algorithm @@ -199,7 +199,7 @@ public: */ TopoDS_Shape getPlane(gp_Trsf *trsf=0); - /** Add a child shape with given operation code + /** Add a child shape with given operation code * * No validation is done at this point. Exception will be thrown when asking * for output shape, if any of the children shapes is not valid or not @@ -217,7 +217,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, bool from_center=false); /** Make a pocket of the combined shape @@ -277,7 +277,7 @@ public: return mySections.size(); } - /** Add a OCC wire shape to CArea + /** Add a OCC wire shape to CArea * * \arg \c area: output converted curved object to here * \arg \c wire: input wire object @@ -287,10 +287,10 @@ public: * \arg \c to_edges: if true, discretize all curves, and insert as open * line segments * */ - static void addWire(CArea &area, const TopoDS_Wire &wire, const gp_Trsf *trsf=NULL, - double deflection=0.01, bool to_edges=false); + static void addWire(CArea &area, const TopoDS_Wire &wire, const gp_Trsf *trsf=NULL, + double deflection=0.01, bool to_edges=false); - /** Add a OCC generic shape to CArea + /** Add a OCC generic shape to CArea * * \arg \c area: output converted curved object to here * \arg \c shape: input shape object @@ -309,7 +309,7 @@ public: * */ static int addShape(CArea &area, const TopoDS_Shape &shape, const gp_Trsf *trsf=NULL, double deflection=0.01,const TopoDS_Shape *plane = NULL, - bool force_coplanar=true, CArea *areaOpen=NULL, bool to_edges=false, + bool force_coplanar=true, CArea *areaOpen=NULL, bool to_edges=false, bool reorient=true); /** Convert curves in CArea into an OCC shape @@ -319,7 +319,7 @@ public: * \arg \c trsf: optional transform matrix to transform the shape back into * its original position. * */ - static TopoDS_Shape toShape(const CArea &area, bool fill, + static TopoDS_Shape toShape(const CArea &area, bool fill, const gp_Trsf *trsf=NULL, int reoirent=0); /** Convert a single curve into an OCC wire @@ -363,14 +363,16 @@ public: * \arg \c shapes: input list of shapes * \arg \c pstart: output start point, * \arg \c pend: optional output containing the ending point of the returned - * + * * See #AREA_PARAMS_PATH for other arguments */ static void toPath(Toolpath &path, const std::list &shapes, const gp_Pnt *pstart=NULL, gp_Pnt *pend=NULL, PARAM_ARGS_DEF(PARAM_FARG,AREA_PARAMS_PATH)); - static int project(TopoDS_Shape &out, const TopoDS_Shape &in, const AreaParams *params=0); + static int project(TopoDS_Shape &out, const TopoDS_Shape &in, + const AreaParams *params = nullptr, + const TopoDS_Shape *work_plane = nullptr); static void setWireOrientation(TopoDS_Wire& wire, const gp_Dir &dir, bool ccw);