Merge pull request #18704 from wwmayer/fix_line_dir

App: Add methods to get base and direction of datum element
This commit is contained in:
Chris Hennes
2025-01-13 10:56:55 -06:00
committed by GitHub
12 changed files with 92 additions and 100 deletions

View File

@@ -45,6 +45,7 @@ PROPERTY_SOURCE(App::Point, App::DatumElement)
PROPERTY_SOURCE(App::LocalCoordinateSystem, App::GeoFeature)
DatumElement::DatumElement(bool hideRole)
: baseDir{0.0, 0.0, 1.0}
{
ADD_PROPERTY_TYPE(Role,
(""),
@@ -63,12 +64,12 @@ DatumElement::~DatumElement() = default;
bool DatumElement::getCameraAlignmentDirection(Base::Vector3d& direction, const char* subname) const
{
Q_UNUSED(subname);
Placement.getValue().getRotation().multVec(Base::Vector3d(0., 0., 1.), direction);
Placement.getValue().getRotation().multVec(baseDir, direction);
return true;
}
App::LocalCoordinateSystem* DatumElement::getLCS()
App::LocalCoordinateSystem* DatumElement::getLCS() const
{
auto inList = getInList();
for (auto* obj : inList) {
@@ -81,12 +82,49 @@ App::LocalCoordinateSystem* DatumElement::getLCS()
return nullptr;
}
bool DatumElement::isOriginFeature()
bool DatumElement::isOriginFeature() const
{
auto lcs = getLCS();
const auto* lcs = getLCS();
return lcs ? lcs->isOrigin() : false;
}
Base::Vector3d DatumElement::getBasePoint() const
{
Base::Placement plc = Placement.getValue();
return plc.getPosition();
}
Base::Vector3d DatumElement::getDirection() const
{
Base::Vector3d dir(baseDir);
Base::Placement plc = Placement.getValue();
Base::Rotation rot = plc.getRotation();
rot.multVec(dir, dir);
return dir;
}
Base::Vector3d DatumElement::getBaseDirection() const
{
return baseDir;
}
void DatumElement::setBaseDirection(const Base::Vector3d& dir)
{
baseDir = dir;
}
// ----------------------------------------------------------------------------
Line::Line()
{
setBaseDirection(Base::Vector3d(1, 0, 0));
}
Point::Point()
{
setBaseDirection(Base::Vector3d(0, 0, 0));
}
// ----------------------------------------------------------------------------
LocalCoordinateSystem::LocalCoordinateSystem()
@@ -206,9 +244,9 @@ const std::vector<LocalCoordinateSystem::SetupData>& LocalCoordinateSystem::getS
{
static const std::vector<SetupData> setupData = {
// clang-format off
{App::Line::getClassTypeId(), AxisRoles[0], tr("X-axis"), Base::Rotation(Base::Vector3d(1, 1, 1), M_PI * 2 / 3)},
{App::Line::getClassTypeId(), AxisRoles[1], tr("Y-axis"), Base::Rotation(Base::Vector3d(-1, 1, 1), M_PI * 2 / 3)},
{App::Line::getClassTypeId(), AxisRoles[2], tr("Z-axis"), Base::Rotation()},
{App::Line::getClassTypeId(), AxisRoles[0], tr("X-axis"), Base::Rotation()},
{App::Line::getClassTypeId(), AxisRoles[1], tr("Y-axis"), Base::Rotation(Base::Vector3d(1, 1, 1), M_PI * 2 / 3)},
{App::Line::getClassTypeId(), AxisRoles[2], tr("Z-axis"), Base::Rotation(Base::Vector3d(1,-1, 1), M_PI * 2 / 3)},
{App::Plane::getClassTypeId(), PlaneRoles[0], tr("XY-plane"), Base::Rotation()},
{App::Plane::getClassTypeId(), PlaneRoles[1], tr("XZ-plane"), Base::Rotation(1.0, 0.0, 0.0, 1.0)},
{App::Plane::getClassTypeId(), PlaneRoles[2], tr("YZ-plane"), Base::Rotation(Base::Vector3d(1, 1, 1), M_PI * 2 / 3)},
@@ -218,7 +256,7 @@ const std::vector<LocalCoordinateSystem::SetupData>& LocalCoordinateSystem::getS
return setupData;
}
DatumElement* LocalCoordinateSystem::createDatum(SetupData& data)
DatumElement* LocalCoordinateSystem::createDatum(const SetupData& data)
{
App::Document* doc = getDocument();
std::string objName = doc->getUniqueObjectName(data.role);
@@ -282,10 +320,6 @@ void LocalCoordinateSystem::onDocumentRestored()
// In 0.22 origins did not have point.
migrateOriginPoint();
// In 0.22 the axis placement were wrong. The X axis had identity placement instead of the Z.
// This was fixed but we need to migrate old files.
migrateXAxisPlacement();
}
void LocalCoordinateSystem::migrateOriginPoint()
@@ -299,33 +333,12 @@ void LocalCoordinateSystem::migrateOriginPoint()
if (std::none_of(features.begin(), features.end(), isOrigin)) {
auto data = getData(PointRoles[0]);
auto* origin = createDatum(data);
origin->purgeTouched();
features.push_back(origin);
OriginFeatures.setValues(features);
}
}
void LocalCoordinateSystem::migrateXAxisPlacement()
{
constexpr const double tolerance = 1e-5;
auto features = OriginFeatures.getValues();
const auto& setupData = getSetupData();
for (auto* obj : features) {
auto* feature = dynamic_cast <App::DatumElement*> (obj);
if (!feature) { continue; }
for (auto data : setupData) {
// ensure the rotation is correct for the role
if (std::strcmp(feature->Role.getValue(), data.role) == 0) {
if (!feature->Placement.getValue().getRotation().isSame(data.rot, tolerance)) {
feature->Placement.setValue(Base::Placement(Base::Vector3d(), data.rot));
getDocument()->setStatus(App::Document::MigrateLCS, true);
}
break;
}
}
}
}
// ----------------------------------------------------------------------------
LocalCoordinateSystem::LCSExtension::LCSExtension(LocalCoordinateSystem* obj)

View File

@@ -50,12 +50,21 @@ public:
~DatumElement() override;
/// Finds the origin object this plane belongs to
App::LocalCoordinateSystem* getLCS();
App::LocalCoordinateSystem* getLCS() const;
Base::Vector3d getBasePoint() const;
Base::Vector3d getDirection() const;
Base::Vector3d getBaseDirection() const;
bool getCameraAlignmentDirection(Base::Vector3d& direction, const char* subname) const override;
/// Returns true if this DatumElement is part of a App::Origin.
bool isOriginFeature();
bool isOriginFeature() const;
protected:
void setBaseDirection(const Base::Vector3d& dir);
private:
Base::Vector3d baseDir;
};
class AppExport Plane: public App::DatumElement
@@ -74,6 +83,7 @@ class AppExport Line: public App::DatumElement
PROPERTY_HEADER_WITH_OVERRIDE(App::DatumElement);
public:
Line();
const char* getViewProviderName() const override
{
return "Gui::ViewProviderLine";
@@ -85,6 +95,7 @@ class AppExport Point: public App::DatumElement
PROPERTY_HEADER_WITH_OVERRIDE(App::DatumElement);
public:
Point();
const char* getViewProviderName() const override
{
return "Gui::ViewProviderPoint";
@@ -197,7 +208,7 @@ public:
/// Points types
static constexpr const char* PointRoles[1] = {"Origin"};
virtual bool isOrigin()
virtual bool isOrigin() const
{
return false;
}
@@ -243,11 +254,10 @@ private:
};
static const std::vector<SetupData>& getSetupData();
DatumElement* createDatum(SetupData& data);
DatumElement* createDatum(const SetupData& data);
SetupData getData(const char* role);
void migrateOriginPoint();
void migrateXAxisPlacement();
};
} // namespace App

View File

@@ -48,10 +48,10 @@ public:
return "Gui::ViewProviderCoordinateSystem";
}
bool isOrigin() override
bool isOrigin() const override
{
return true;
};
}
};
} // namespace App

View File

@@ -114,36 +114,6 @@ void StdCmdOpen::activated(int iMsg)
"likely result in loss of data."));
}
};
auto checkMigrationLCS = [](App::Document* doc) {
if (doc && doc->testStatus(App::Document::MigrateLCS)) {
auto grp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/View");
if (!grp->GetBool("ShowLCSMigrationWarning", true)) {
return;
}
// Display the warning message
QMessageBox msgBox(QMessageBox::Warning,
QObject::tr("File Migration Warning"),
QObject::tr("This file was created with an older version of %1. "
"Origin axes had incorrect placements, which have now been corrected.\n\n"
"However, if you save this file in the current version and reopen it in an"
" older version of %1, the origin axes will be misaligned. Additionally, "
"if your file references these origin axes, your file will likely be broken.")
.arg(QApplication::applicationName()),
QMessageBox::Ok);
QCheckBox* checkBox = new QCheckBox(QObject::tr("Don't show this warning again"));
msgBox.setCheckBox(checkBox);
msgBox.exec();
// Save preference if the user selects "Don't show again"
if (checkBox->isChecked()) {
grp->SetBool("ShowLCSMigrationWarning", false);
}
}
};
// clang-format on
Q_UNUSED(iMsg);
@@ -215,7 +185,6 @@ void StdCmdOpen::activated(int iMsg)
checkPartialRestore(doc);
checkRestoreError(doc);
checkMigrationLCS(doc);
}
}
}

View File

@@ -33,6 +33,7 @@
#endif
#include <App/Datums.h>
#include <Gui/Utilities.h>
#include <Gui/ViewParams.h>
#include "ViewProviderLine.h"
@@ -53,7 +54,8 @@ ViewProviderLine::ViewProviderLine()
ViewProviderLine::~ViewProviderLine() = default;
void ViewProviderLine::attach(App::DocumentObject *obj) {
void ViewProviderLine::attach(App::DocumentObject *obj)
{
ViewProviderDatum::attach(obj);
// Setup label text and line colors
@@ -82,14 +84,16 @@ void ViewProviderLine::attach(App::DocumentObject *obj) {
static const float size = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/View")->GetFloat("DatumLineSize", 70.0);
auto line = getObject<App::Line>();
Base::Vector3d dir = line->getBaseDirection();
SbVec3f verts[2];
if (noRole) {
verts[0] = SbVec3f(0, 0, 2 * size);
verts[0] = Base::convertTo<SbVec3f>(dir * 2 * size);
verts[1] = SbVec3f(0, 0, 0);
}
else {
verts[0] = SbVec3f(0, 0, size);
verts[1] = SbVec3f(0, 0, 0.2 * size);
verts[0] = Base::convertTo<SbVec3f>(dir * size);
verts[1] = Base::convertTo<SbVec3f>(dir * 0.2 * size);
}
// indexes used to create the edges
@@ -108,7 +112,7 @@ void ViewProviderLine::attach(App::DocumentObject *obj) {
sep->addChild ( pLines );
auto textTranslation = new SoTranslation ();
textTranslation->translation.setValue(SbVec3f(0, 0, size * 1.1));
textTranslation->translation.setValue(Base::convertTo<SbVec3f>(dir * 1.1 * size));
sep->addChild ( textTranslation );
auto ps = new SoPickStyle();

View File

@@ -516,14 +516,12 @@ const Base::Vector3d Constraint::getDirection(const App::PropertyLinkSub& direct
}
if (obj->isDerivedFrom<App::Line>()) {
Base::Vector3d vec(1.0, 0.0, 0.0);
static_cast<App::Line*>(obj)->Placement.getValue().multVec(vec, vec);
Base::Vector3d vec = static_cast<App::Line*>(obj)->getDirection();
return vec;
}
if (obj->isDerivedFrom<App::Plane>()) {
Base::Vector3d vec(0.0, 0.0, 1.0);
static_cast<App::Plane*>(obj)->Placement.getValue().multVec(vec, vec);
Base::Vector3d vec = static_cast<App::Plane*>(obj)->getDirection();
return vec;
}

View File

@@ -69,6 +69,7 @@
#include <Base/Placement.h>
#include <Base/Rotation.h>
#include <Base/Stream.h>
#include <Base/Tools.h>
#include <Mod/Material/App/MaterialManager.h>
#include "Geometry.h"
@@ -76,7 +77,7 @@
#include "PartFeaturePy.h"
#include "PartPyCXX.h"
#include "TopoShapePy.h"
#include "Base/Tools.h"
#include "Tools.h"
using namespace Part;
namespace sp = std::placeholders;
@@ -993,7 +994,9 @@ static TopoShape _getTopoShape(const App::DocumentObject* obj,
if (linked->isDerivedFrom(App::Line::getClassTypeId())) {
static TopoDS_Shape _shape;
if (_shape.IsNull()) {
BRepBuilderAPI_MakeEdge builder(gp_Lin(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)));
auto line = static_cast<App::Line*>(linked);
Base::Vector3d dir = line->getBaseDirection();
BRepBuilderAPI_MakeEdge builder(gp_Lin(gp_Pnt(0, 0, 0), Base::convertTo<gp_Dir>(dir)));
_shape = builder.Shape();
_shape.Infinite(Standard_True);
}
@@ -1002,7 +1005,9 @@ static TopoShape _getTopoShape(const App::DocumentObject* obj,
else if (linked->isDerivedFrom(App::Plane::getClassTypeId())) {
static TopoDS_Shape _shape;
if (_shape.IsNull()) {
BRepBuilderAPI_MakeFace builder(gp_Pln(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)));
auto plane = static_cast<App::Plane*>(linked);
Base::Vector3d dir = plane->getBaseDirection();
BRepBuilderAPI_MakeFace builder(gp_Pln(gp_Pnt(0, 0, 0), Base::convertTo<gp_Dir>(dir)));
_shape = builder.Shape();
_shape.Infinite(Standard_True);
}

View File

@@ -161,9 +161,7 @@ const std::list<gp_Trsf> LinearPattern::getTransformations(const std::vector<App
dir = gp_Dir(d.x, d.y, d.z);
} else if (refObject->isDerivedFrom<App::Line>()) {
App::Line* line = static_cast<App::Line*>(refObject);
Base::Rotation rot = line->Placement.getValue().getRotation();
Base::Vector3d d(1,0,0);
rot.multVec(d, d);
Base::Vector3d d = line->getDirection();
dir = gp_Dir(d.x, d.y, d.z);
} else if (refObject->isDerivedFrom<Part::Feature>()) {
if (subStrings[0].empty())

View File

@@ -116,11 +116,9 @@ const std::list<gp_Trsf> Mirrored::getTransformations(const std::vector<App::Doc
getMirrorAxis axisOfPlane = [this](gp_Pnt& axbase, gp_Dir& axdir) {
App::DocumentObject* refObject = MirrorPlane.getValue();
if (auto plane = dynamic_cast<App::Plane*>(refObject)) {
Base::Vector3d base = plane->Placement.getValue().getPosition();
Base::Vector3d base = plane->getBasePoint();
axbase = gp_Pnt(base.x, base.y, base.z);
Base::Rotation rot = plane->Placement.getValue().getRotation();
Base::Vector3d dir(0,0,1);
rot.multVec(dir, dir);
Base::Vector3d dir = plane->getDirection();
axdir = gp_Dir(dir.x, dir.y, dir.z);
return true;
}

View File

@@ -129,9 +129,7 @@ const std::list<gp_Trsf> PolarPattern::getTransformations(const std::vector<App:
axdir = gp_Dir(dir.x, dir.y, dir.z);
} else if (refObject->isDerivedFrom<App::Line>()) {
App::Line* line = static_cast<App::Line*>(refObject);
Base::Rotation rot = line->Placement.getValue().getRotation();
Base::Vector3d d(1,0,0);
rot.multVec(d, d);
Base::Vector3d d = line->getDirection();
axdir = gp_Dir(d.x, d.y, d.z);
} else if (refObject->isDerivedFrom<Part::Feature>()) {
if (subStrings[0].empty())

View File

@@ -1358,9 +1358,8 @@ void ProfileBased::getAxis(const App::DocumentObject * pcReferenceAxis, const st
if (pcReferenceAxis->isDerivedFrom<App::Line>()) {
auto* line = static_cast<const App::Line*>(pcReferenceAxis);
Base::Placement plc = line->Placement.getValue();
base = plc.getPosition();
plc.getRotation().multVec(Base::Vector3d(0, 0, 1), dir);
base = line->getBasePoint();
dir = line->getDirection();
verifyAxisFunc(checkAxis, sketchplane, gp_Dir(dir.x, dir.y, dir.z));
return;

View File

@@ -357,17 +357,17 @@ class DocumentBasicCases(unittest.TestCase):
res = obj.getSubObject("X_Axis", retType=2)
self.assertEqual(
res[1].multVec(FreeCAD.Vector(0, 0, 1)).getAngle(FreeCAD.Vector(1, 0, 0)), 0.0
res[1].multVec(FreeCAD.Vector(1, 0, 0)).getAngle(FreeCAD.Vector(1, 0, 0)), 0.0
)
res = obj.getSubObject("Y_Axis", retType=2)
self.assertEqual(
res[1].multVec(FreeCAD.Vector(0, 0, 1)).getAngle(FreeCAD.Vector(0, 1, 0)), 0.0
res[1].multVec(FreeCAD.Vector(1, 0, 0)).getAngle(FreeCAD.Vector(0, 1, 0)), 0.0
)
res = obj.getSubObject("Z_Axis", retType=2)
self.assertEqual(
res[1].multVec(FreeCAD.Vector(0, 0, 1)).getAngle(FreeCAD.Vector(0, 0, 1)), 0.0
res[1].multVec(FreeCAD.Vector(1, 0, 0)).getAngle(FreeCAD.Vector(0, 0, 1)), 0.0
)
res = obj.getSubObject("XY_Plane", retType=2)