PD: fix gizmo direction when the calculated point lies outside the face (#26616)

* PD: fix gizmo direction when the calculated point lies outside the face

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
Captain
2026-01-05 17:14:01 +05:30
committed by GitHub
parent 92529da3fc
commit 2b97d553f9
3 changed files with 67 additions and 35 deletions

View File

@@ -43,23 +43,24 @@
EdgeMidPointProps getEdgeMidPointProps(Part::TopoShape& edge)
{
std::unique_ptr<Part::Geometry> geom = Part::Geometry::fromShape(edge.getShape());
auto curve = freecad_cast<Part::GeomCurve*>(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<Base::Vector3d>(pos);
auto tangent = Base::convertTo<Base::Vector3d>(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<Base::Vector3d>(massProps.CentreOfMass());
}
std::optional<std::pair<Base::Vector3d, Base::Vector3d>> 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<Base::Vector3d>(_inwardPoint), Base::convertTo<Base::Vector3d>(_normal)}};
BOPTools_AlgoTools3D::GetNormalToFaceOnEdge(TDSedge, face, middle, normal, context);
props.position = Base::convertTo<Base::Vector3d>(inwardPoint);
props.normal = Base::convertTo<Base::Vector3d>(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<Part::TopoShape> getAdjacentEdgesFromFace(Part::TopoShape& face)

View File

@@ -39,7 +39,20 @@ EdgeMidPointProps PartExport getEdgeMidPointProps(Part::TopoShape& edge);
Base::Vector3d PartExport getCentreOfMassFromFace(TopoDS_Face& face);
std::optional<std::pair<Base::Vector3d, Base::Vector3d>> 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);

View File

@@ -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
);