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:
@@ -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];
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user