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:
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user