Attacher: Orient normals correctly for Midpoint

Co-authored-by: Max Wilfinger <max@wilfinger.de>
This commit is contained in:
Kacper Donat
2025-07-15 00:14:39 +02:00
committed by Benjamin Nauck
parent 7e0d2d21f7
commit 6f3f0b1d0d
3 changed files with 30 additions and 15 deletions

View File

@@ -1969,32 +1969,38 @@ AttachEngine3D::_calculateAttachedPlacement(const std::vector<App::DocumentObjec
case TopAbs_FACE: {
auto surface = freecad_cast<GeomSurface*>(geom.get());
auto face = TopoDS::Face(shape->getShape());
auto adaptorSurface = BRepAdaptor_Surface(face, true);
auto u1 = adaptorSurface.FirstUParameter();
auto u2 = adaptorSurface.LastUParameter();
auto v1 = adaptorSurface.FirstVParameter();
auto v2 = adaptorSurface.LastVParameter();
auto midU = (u1 + u2) / 2;
auto midV = (v1 + v2) / 2;
if (auto sphere = freecad_cast<GeomSphere*>(geom.get())) {
placement.setPosition(sphere->getLocation());
} else if (auto cone = freecad_cast<GeomCone*>(geom.get())) {
placement.setPosition(cone->getApex());
} else if (auto point = surface->point(midU, midV)) {
placement.setPosition(*point);
} else if (auto com = shape->centerOfGravity()) {
placement.setPosition(*com);
} else {
placement.setPosition(shape->getBoundBox().GetCenter());
}
if (auto rotation = surface->getRotation()) {
placement.setRotation(*rotation);
} else {
auto adaptorSurface = BRepAdaptor_Surface(TopoDS::Face(shape->getShape()), true);
// calculate the normal at midpoint of the surface and use it as Z axis
gp_Dir dir;
surface->normal(midU, midV, dir);
auto u1 = adaptorSurface.FirstUParameter();
auto u2 = adaptorSurface.LastUParameter();
auto v1 = adaptorSurface.FirstVParameter();
auto v2 = adaptorSurface.LastVParameter();
// calculate the normal at midpoint of the surface and use it as Z axis
gp_Dir dir;
surface->normal((u1 + u2) / 2, (v1 + v2) / 2, dir);
placement.setRotation(Base::Rotation::fromNormalVector(Base::convertTo<Base::Vector3d>(-dir)));
if (face.Orientation() == TopAbs_REVERSED) {
dir = -dir;
}
placement.setRotation(Base::Rotation::fromNormalVector(Base::convertTo<Base::Vector3d>(dir)));
}
break;

View File

@@ -4884,12 +4884,19 @@ bool GeomSurface::normal(double u, double v, gp_Dir& dir) const
Tools::getNormal(s, u, v, Precision::Confusion(), dir, done);
if (done)
if (done) {
return true;
}
return false;
}
std::optional<Base::Vector3d> GeomSurface::point(double u, double v) const
{
Handle(Geom_Surface) s = Handle(Geom_Surface)::DownCast(handle());
return Base::convertTo<Base::Vector3d>(s->Value(u, v));
}
gp_Vec GeomSurface::getDN(double u, double v, int Nu, int Nv) const
{
Handle(Geom_Surface) s = Handle(Geom_Surface)::DownCast(handle());

View File

@@ -889,6 +889,8 @@ public:
bool tangentU(double u, double v, gp_Dir& dirU) const;
bool tangentV(double u, double v, gp_Dir& dirV) const;
bool normal(double u, double v, gp_Dir& dir) const;
std::optional<Base::Vector3d> point(double u, double v) const;
/*!
Computes the derivative of order Nu in the direction U and Nv
in the direction V at the point P(U, V).