diff --git a/src/Mod/Part/App/GizmoHelper.cpp b/src/Mod/Part/App/GizmoHelper.cpp index 1e8dec2e1f..9492301be1 100644 --- a/src/Mod/Part/App/GizmoHelper.cpp +++ b/src/Mod/Part/App/GizmoHelper.cpp @@ -43,23 +43,24 @@ EdgeMidPointProps getEdgeMidPointProps(Part::TopoShape& edge) { - std::unique_ptr geom = Part::Geometry::fromShape(edge.getShape()); - auto curve = freecad_cast(geom.get()); - double u1 = curve->getFirstParameter(); - double u2 = curve->getLastParameter(); - double middle = (u1 + u2) / 2; - Base::Vector3d position = curve->pointAtParameter(middle); + double u1, u2; + TopoDS_Edge TDSEdge = TopoDS::Edge(edge.getShape()); + Handle(Geom_Curve) curve = BRep_Tool::Curve(TDSEdge, u1, u2); + double middle = (u1 + u2) / 2.0; - Base::Vector3d tangent; - bool ret = curve->tangent(middle, tangent); - if (ret) { - return {position, tangent, middle}; + gp_Pnt pos; + gp_Vec derivative; + curve->D1(middle, pos, derivative); + + auto position = Base::convertTo(pos); + auto tangent = Base::convertTo(derivative); + tangent.Normalize(); + + if (TDSEdge.Orientation() == TopAbs_REVERSED) { + tangent = -tangent; } - Base::Console().error( - "Failed to calculate tangent for the draggers! Please file a bug report for this." - ); - return {position, Base::Vector3d {0, 0, 0}, middle}; + return {position, tangent, middle}; } Base::Vector3d getCentreOfMassFromFace(TopoDS_Face& face) @@ -69,30 +70,41 @@ Base::Vector3d getCentreOfMassFromFace(TopoDS_Face& face) return Base::convertTo(massProps.CentreOfMass()); } -std::optional> getFaceNormalFromPointNearEdge( +PointOnFaceNearEdgeProps getFaceNormalFromPointNearEdge( Part::TopoShape& edge, double middle, TopoDS_Face& face ) { - auto _edge = TopoDS::Edge(edge.getShape()); + auto TDSedge = TopoDS::Edge(edge.getShape()); - gp_Pnt _inwardPoint; - gp_Dir _normal; + gp_Pnt inwardPoint; + gp_Pnt2d inwardPoint2d; + gp_Dir normal; Handle(IntTools_Context) context = new IntTools_Context; - if (!BOPTools_AlgoTools3D::GetApproxNormalToFaceOnEdge( - _edge, - face, - middle, - _inwardPoint, - _normal, - context - )) { - return std::nullopt; + int res + = BOPTools_AlgoTools3D::PointNearEdge(TDSedge, face, middle, inwardPoint2d, inwardPoint, context); + + PointOnFaceNearEdgeProps props; + switch (res) { + case 0: + props.state = PointOnFaceNearEdgeProps::State::OnFace; + break; + case 2: + props.state = PointOnFaceNearEdgeProps::State::OutsideFace; + break; + default: + props.state = PointOnFaceNearEdgeProps::State::Undefined; + return props; } - return {{Base::convertTo(_inwardPoint), Base::convertTo(_normal)}}; + BOPTools_AlgoTools3D::GetNormalToFaceOnEdge(TDSedge, face, middle, normal, context); + + props.position = Base::convertTo(inwardPoint); + props.normal = Base::convertTo(normal); + + return props; } Base::Vector3d getFaceNormalFromPoint(Base::Vector3d& point, TopoDS_Face& face) @@ -132,9 +144,10 @@ DraggerPlacementProps getDraggerPlacementFromEdgeAndFace(Part::TopoShape& edge, Base::Vector3d normal; Base::Vector3d inwardPoint; - if (auto ret = getFaceNormalFromPointNearEdge(edge, middle, face)) { - inwardPoint = ret->first; - normal = ret->second; + auto props = getFaceNormalFromPointNearEdge(edge, middle, face); + if (props.state != PointOnFaceNearEdgeProps::State::Undefined) { + inwardPoint = props.position; + normal = props.normal; } else { // Failed to compute the normal at a point on the face near the edge @@ -151,13 +164,19 @@ DraggerPlacementProps getDraggerPlacementFromEdgeAndFace(Part::TopoShape& edge, dir = -dir; } + // Assumption: Since the point is very close to the edge but lies outside + // the face we can reverse the direction to point towards the face material + if (props.state == PointOnFaceNearEdgeProps::State::OutsideFace) { + dir = -dir; + } + return {position, dir, tangent}; } DraggerPlacementProps getDraggerPlacementFromEdgeAndFace(Part::TopoShape& edge, Part::TopoShape& face) { - TopoDS_Face _face = TopoDS::Face(face.getShape()); - return getDraggerPlacementFromEdgeAndFace(edge, _face); + TopoDS_Face TDSFace = TopoDS::Face(face.getShape()); + return getDraggerPlacementFromEdgeAndFace(edge, TDSFace); } std::vector getAdjacentEdgesFromFace(Part::TopoShape& face) diff --git a/src/Mod/Part/App/GizmoHelper.h b/src/Mod/Part/App/GizmoHelper.h index 9be87e6609..045d6287fb 100644 --- a/src/Mod/Part/App/GizmoHelper.h +++ b/src/Mod/Part/App/GizmoHelper.h @@ -39,7 +39,20 @@ EdgeMidPointProps PartExport getEdgeMidPointProps(Part::TopoShape& edge); Base::Vector3d PartExport getCentreOfMassFromFace(TopoDS_Face& face); -std::optional> PartExport +struct PartExport PointOnFaceNearEdgeProps +{ + enum class State : std::uint8_t + { + OnFace, + OutsideFace, + Undefined + }; + + Base::Vector3d position; + Base::Vector3d normal; + State state; +}; +PointOnFaceNearEdgeProps PartExport getFaceNormalFromPointNearEdge(Part::TopoShape& edge, double middle, TopoDS_Face& face); Base::Vector3d PartExport getFaceNormalFromPoint(Base::Vector3d& point, TopoDS_Face& face); diff --git a/src/Mod/Part/Gui/TaskThickness.cpp b/src/Mod/Part/Gui/TaskThickness.cpp index a6eaf24831..c6df2bfdde 100644 --- a/src/Mod/Part/Gui/TaskThickness.cpp +++ b/src/Mod/Part/Gui/TaskThickness.cpp @@ -361,7 +361,7 @@ void ThicknessWidget::setGizmoPositions() } Part::Thickness* thickness = getObject(); - auto base = thickness->getTopoShape( + auto base = Part::Thickness::getTopoShape( thickness->Faces.getValue(), Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform );