Part: Add midpoint attachement mode

This adds midpoint attachement mode to Attacher. It works just like
method for finding placement of JCS in Assembly.
This commit is contained in:
Kacper Donat
2024-11-11 17:59:07 +01:00
parent 49ff7b8bf0
commit 88141d6dce
6 changed files with 155 additions and 11 deletions

View File

@@ -81,6 +81,12 @@ Rotation::Rotation(const Vector3d& rotateFrom, const Vector3d& rotateTo)
this->setValue(rotateFrom, rotateTo);
}
Rotation Rotation::fromNormalVector(const Vector3d& normal)
{
// We rotate Z axis to be aligned with the supplied normal vector
return Rotation(Vector3d(0, 0, 1), normal);
}
const double* Rotation::getValue() const
{
return &this->quat[0];

View File

@@ -49,6 +49,9 @@ public:
Rotation(const Rotation& rot) = default;
Rotation(Rotation&& rot) = default;
~Rotation() = default;
/// Utility function to create Rotation based on direction / normal vector
static Rotation fromNormalVector(const Vector3d& normal);
//@}
/** Methods to get or set rotations. */

View File

@@ -69,6 +69,8 @@
#include "AttachExtension.h"
#include "Tools.h"
#include <Geometry.h>
using namespace Part;
using namespace Attacher;
@@ -136,6 +138,7 @@ const char* AttachEngine::eMapModeStrings[]= {
"OYX",
"ParallelPlane",
"MidPoint",
nullptr};
@@ -1895,6 +1898,83 @@ AttachEngine3D::_calculateAttachedPlacement(const std::vector<App::DocumentObjec
plm *= this->attachmentOffset;
return plm;
} break;
case mmMidpoint: {
Base::Placement placement;
auto shape = shapes.front();
auto geom = Geometry::fromShape(shape->getShape());
switch (shape->shapeType()) {
case TopAbs_VERTEX: {
if (auto point = dynamic_cast<GeomPoint*>(geom.get())) {
placement.setPosition(point->getPoint());
}
}
break;
case TopAbs_EDGE: {
if (auto conic = dynamic_cast<GeomConic*>(geom.get())) {
placement.setPosition(conic->getLocation());
placement.setRotation(conic->getRotation().value_or(Base::Rotation {}));
} else if (auto line = dynamic_cast<GeomCurve*>(geom.get())) {
auto u1 = line->getFirstParameter();
auto u2 = line->getLastParameter();
auto middle = (u1 + u2) / 2;
placement.setPosition(line->pointAtParameter(middle));
Base::Vector3d direction;
if (!line->normalAt(middle, direction)) {
line->tangent(middle, direction);
}
placement.setRotation(Base::Rotation::fromNormalVector(-direction));
}
}
break;
case TopAbs_FACE: {
auto surface = dynamic_cast<GeomSurface*>(geom.get());
if (auto sphere = dynamic_cast<GeomSphere*>(geom.get())) {
placement.setPosition(sphere->getLocation());
} else if (auto cone = dynamic_cast<GeomCone*>(geom.get())) {
placement.setPosition(cone->getApex());
} else {
placement.setPosition(shape->centerOfGravity().value());
}
if (auto rotation = surface->getRotation()) {
placement.setRotation(*rotation);
} else {
auto adaptorSurface = BRepAdaptor_Surface(TopoDS::Face(shape->getShape()), true);
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)));
}
}
break;
default:
THROWM(Base::TypeError,
"AttachEngine3D::calculateAttachedPlacement: Unsupported shape type, "
"must be one of: Vertex, Edge, Face");
break;
}
return placement * attachmentOffset;
break;
}
default:
throwWrongMode(mmode);
} // switch (MapMode)

View File

@@ -108,6 +108,7 @@ enum eMapMode {
mmOYX,
mmParallelPlane,
mmMidpoint,
mmDummy_NumberOfModes//a value useful to check the validity of mode value
};//see also eMapModeStrings[] definition in .cpp

View File

@@ -149,6 +149,8 @@
#include "ToroidPy.h"
#include "TopoShape.h"
#include <gp_Quaternion.hxx>
#if OCC_VERSION_HEX >= 0x070600
using GeomAdaptor_HCurve = GeomAdaptor_Curve;
@@ -2127,10 +2129,25 @@ void GeomConic::setLocation(const Base::Vector3d& Center)
Base::Vector3d GeomConic::getCenter() const
{
Handle(Geom_Conic) conic = Handle(Geom_Conic)::DownCast(handle());
Handle(Geom_Conic) conic = Handle(Geom_Conic)::DownCast(handle());
gp_Ax1 axis = conic->Axis();
const gp_Pnt& loc = axis.Location();
return Base::Vector3d(loc.X(),loc.Y(),loc.Z());
return Base::Vector3d(loc.X(), loc.Y(), loc.Z());
}
std::optional<Base::Rotation> GeomConic::getRotation() const
{
Handle(Geom_Conic) conic = Handle(Geom_Conic)::DownCast(handle());
if (!conic) {
return {};
}
gp_Trsf trsf;
trsf.SetTransformation(conic->Position(), gp_Ax3());
auto q = trsf.GetRotation();
return Base::Rotation(q.X(), q.Y(), q.Z(), q.W());
}
void GeomConic::setCenter(const Base::Vector3d& Center)
@@ -2142,7 +2159,6 @@ void GeomConic::setCenter(const Base::Vector3d& Center)
conic->SetLocation(p1);
}
catch (Standard_Failure& e) {
THROWM(Base::CADKernelError,e.GetMessageString())
}
}
@@ -4803,28 +4819,36 @@ GeomPlane* GeomSurface::toPlane(bool clone, double tol) const
if (isDerivedFrom(GeomPlane::getClassTypeId())) {
if (clone) {
return dynamic_cast<GeomPlane*>(this->clone());
} else {
}
else {
return dynamic_cast<GeomPlane*>(this->copy());
}
}
gp_Pln pln;
if (!isPlanar(&pln, tol))
if (!isPlanar(&pln, tol)) {
return nullptr;
}
auto res = new GeomPlane(pln);
res->copyNonTag(this);
if (clone)
if (clone) {
res->tag = this->tag;
}
return res;
}
std::optional<Base::Rotation> GeomSurface::getRotation() const
{
return {};
}
TopoDS_Shape GeomSurface::toShape() const
{
Handle(Geom_Surface) s = Handle(Geom_Surface)::DownCast(handle());
Standard_Real u1,u2,v1,v2;
s->Bounds(u1,u2,v1,v2);
BRepBuilderAPI_MakeFace mkBuilder(s, u1, u2, v1, v2, Precision::Confusion() );
Standard_Real u1, u2, v1, v2;
s->Bounds(u1, u2, v1, v2);
BRepBuilderAPI_MakeFace mkBuilder(s, u1, u2, v1, v2, Precision::Confusion());
return mkBuilder.Shape();
}
@@ -5180,9 +5204,24 @@ GeomElementarySurface::~GeomElementarySurface()
Base::Vector3d GeomElementarySurface::getLocation(void) const
{
Handle(Geom_ElementarySurface) surf = Handle(Geom_ElementarySurface)::DownCast(handle());
Handle(Geom_ElementarySurface) surf = Handle(Geom_ElementarySurface)::DownCast(handle());
gp_Pnt loc = surf->Location();
return Base::Vector3d(loc.X(),loc.Y(),loc.Z());
return Base::Vector3d(loc.X(), loc.Y(), loc.Z());
}
std::optional<Base::Rotation> GeomPlane::getRotation() const
{
Handle(Geom_ElementarySurface) s = Handle(Geom_ElementarySurface)::DownCast(handle());
if (!s) {
return {};
}
gp_Trsf trsf;
trsf.SetTransformation(s->Position().Ax2(),gp_Ax3());
auto q = trsf.GetRotation();
return Base::Rotation(q.X(),q.Y(),q.Z(),q.W());
}
Base::Vector3d GeomElementarySurface::getDir(void) const
@@ -5411,6 +5450,12 @@ double GeomCone::getSemiAngle() const
return mySurface->SemiAngle();
}
Base::Vector3d GeomCone::getApex() const
{
Handle(Geom_ConicalSurface) s = Handle(Geom_ConicalSurface)::DownCast(handle());
return Base::convertTo<Base::Vector3d>(s->Apex());
}
bool GeomCone::isSame(const Geometry &_other, double tol, double atol) const
{
if(_other.getTypeId() != getTypeId())

View File

@@ -58,6 +58,7 @@
#include <list>
#include <memory>
#include <vector>
#include <optional>
#include <boost/uuid/uuid_generators.hpp>
@@ -409,6 +410,7 @@ public:
*/
Base::Vector3d getCenter() const;
Base::Vector3d getLocation() const;
std::optional<Base::Rotation> getRotation() const;
void setLocation(const Base::Vector3d& Center);
/*!
* \deprecated use setLocation
@@ -882,6 +884,8 @@ public:
GeomPlane *toPlane(bool clone=true, double tol=1e-7) const;
virtual std::optional<Base::Rotation> getRotation() const;
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;
@@ -961,6 +965,7 @@ public:
~GeomElementarySurface() override;
Base::Vector3d getLocation() const;
Base::Vector3d getDir() const;
Base::Vector3d getXDir() const;
Base::Vector3d getYDir() const;
@@ -1014,6 +1019,8 @@ public:
double getRadius() const;
double getSemiAngle() const;
Base::Vector3d getApex() const;
bool isSame(const Geometry &other, double tol, double atol) const override;
void setHandle(const Handle(Geom_ConicalSurface)&);
@@ -1091,6 +1098,8 @@ public:
~GeomPlane() override;
Geometry *copy() const override;
std::optional<Base::Rotation> getRotation() const override;
// Persistence implementer ---------------------
unsigned int getMemSize() const override;
void Save(Base::Writer &/*writer*/) const override;