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:
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -48,10 +48,10 @@ public:
|
||||
return "Gui::ViewProviderCoordinateSystem";
|
||||
}
|
||||
|
||||
bool isOrigin() override
|
||||
bool isOrigin() const override
|
||||
{
|
||||
return true;
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace App
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user