diff --git a/src/Mod/Sketcher/App/SketchObject.cpp b/src/Mod/Sketcher/App/SketchObject.cpp index 4c9b8be7fe..7b7200a00c 100644 --- a/src/Mod/Sketcher/App/SketchObject.cpp +++ b/src/Mod/Sketcher/App/SketchObject.cpp @@ -8977,16 +8977,58 @@ void processEdge(const TopoDS_Edge& edge, } else { try { - BRepOffsetAPI_NormalProjection mkProj(aProjFace); - mkProj.Add(edge); - mkProj.Build(); - const TopoDS_Shape& projShape = mkProj.Projection(); - if (!projShape.IsNull()) { - TopExp_Explorer xp; - for (xp.Init(projShape, TopAbs_EDGE); xp.More(); xp.Next()) { - TopoDS_Edge projEdge = TopoDS::Edge(xp.Current()); - TopLoc_Location loc(mov); - projEdge.Location(loc); + Part::TopoShape projShape; + // Projection of the edge on parallel plane to the sketch plane is edge itself + // all we need to do is match coordinate systems + // for some reason OCC doesn't like to project a planar B-Spline to a plane parallel to it + if (planar && plane.Axis().Direction().IsParallel(sketchPlane.Axis().Direction(), Precision::Confusion())) { + TopoDS_Edge projEdge = edge; + + // We need to trim the curve in case we are projecting a B-Spline segment + if(curve.GetType() == GeomAbs_BSplineCurve){ + double Param1 = curve.FirstParameter(); + double Param2 = curve.LastParameter(); + + if (Param1 > Param2){ + std::swap(Param1, Param2); + } + + // trim curve in case we are projecting a segment + auto bsplineCurve = curve.BSpline(); + if(Param2 - Param1 > Precision::Confusion()){ + bsplineCurve->Segment(Param1, Param2); + projEdge = BRepBuilderAPI_MakeEdge(bsplineCurve).Edge(); + } + } + + projShape.setShape(projEdge); + + // We can't use gp_Pln::Distance() because we need to + // know which side the plane is regarding the sketch + const gp_Pnt& aP = sketchPlane.Location(); + const gp_Pnt& aLoc = plane.Location (); + const gp_Dir& aDir = plane.Axis().Direction(); + double d = (aDir.X() * (aP.X() - aLoc.X()) + + aDir.Y() * (aP.Y() - aLoc.Y()) + + aDir.Z() * (aP.Z() - aLoc.Z())); + + gp_Trsf trsf; + trsf.SetTranslation(gp_Vec(aDir) * d); + projShape.transformShape(Part::TopoShape::convert(trsf), /*copy*/false); + } else { + // When planes not parallel or perpendicular, or edge is not planar + // normal projection is working just fine + BRepOffsetAPI_NormalProjection mkProj(aProjFace); + mkProj.Add(edge); + mkProj.Build(); + + projShape.setShape(mkProj.Projection()); + } + if (!projShape.isNull() && projShape.hasSubShape(TopAbs_EDGE)) { + for (auto &e : projShape.getSubTopoShapes(TopAbs_EDGE)) { + // Transform copy of the edge to the sketch plane local coordinates + e.transformShape(invPlm.toMatrix(), /*copy*/true, /*checkScale*/true); + TopoDS_Edge projEdge = TopoDS::Edge(e.getShape()); processEdge2(projEdge, geos); } }