Merge pull request #15262 from Rexbas/fix-alignment-direction

Move getGlobalPlacement() and fix alignment direction for transformed objects
This commit is contained in:
Chris Hennes
2024-09-13 13:09:23 -06:00
committed by GitHub
11 changed files with 143 additions and 140 deletions

View File

@@ -111,39 +111,6 @@ static void printPlacement(Base::Placement plc, const char* name)
angle);
}*/
static bool isLink(App::DocumentObject* obj)
{
if (!obj) {
return false;
}
auto* link = dynamic_cast<App::Link*>(obj);
if (link) {
return link->ElementCount.getValue() == 0;
}
auto* linkEl = dynamic_cast<App::LinkElement*>(obj);
if (linkEl) {
return true;
}
return false;
}
static bool isLinkGroup(App::DocumentObject* obj)
{
if (!obj) {
return false;
}
auto* link = dynamic_cast<App::Link*>(obj);
if (link) {
return link->ElementCount.getValue() > 0;
}
return false;
}
// ================================ Assembly Object ============================
PROPERTY_SOURCE(Assembly::AssemblyObject, App::Part)
@@ -1733,7 +1700,7 @@ void AssemblyObject::ensureIdentityPlacements()
std::vector<App::DocumentObject*> group = Group.getValues();
for (auto* obj : group) {
// When used in assembly, link groups must have identity placements.
if (isLinkGroup(obj)) {
if (obj->isLinkGroup()) {
auto* link = dynamic_cast<App::Link*>(obj);
auto* pPlc = dynamic_cast<App::PropertyPlacement*>(obj->getPropertyByName("Placement"));
if (!pPlc || !link) {
@@ -2078,6 +2045,7 @@ void AssemblyObject::setJointActivated(App::DocumentObject* joint, bool val)
propActivated->setValue(val);
}
}
bool AssemblyObject::getJointActivated(App::DocumentObject* joint)
{
auto* propActivated = dynamic_cast<App::PropertyBool*>(joint->getPropertyByName("Activated"));
@@ -2087,65 +2055,6 @@ bool AssemblyObject::getJointActivated(App::DocumentObject* joint)
return false;
}
Base::Placement AssemblyObject::getPlacementFromProp(App::DocumentObject* obj, const char* propName)
{
Base::Placement plc = Base::Placement();
auto* propPlacement = dynamic_cast<App::PropertyPlacement*>(obj->getPropertyByName(propName));
if (propPlacement) {
plc = propPlacement->getValue();
}
return plc;
}
Base::Placement AssemblyObject::getGlobalPlacement(App::DocumentObject* targetObj,
App::DocumentObject* rootObj,
const std::string& sub)
{
if (!targetObj || !rootObj || sub == "") {
return Base::Placement();
}
std::vector<std::string> names = splitSubName(sub);
App::Document* doc = rootObj->getDocument();
Base::Placement plc = getPlacementFromProp(rootObj, "Placement");
for (auto& name : names) {
App::DocumentObject* obj = doc->getObject(name.c_str());
if (!obj) {
return Base::Placement();
}
plc = plc * getPlacementFromProp(obj, "Placement");
if (obj == targetObj) {
return plc;
}
if (isLink(obj)) {
// Update doc in case its an external link.
doc = obj->getLinkedObject()->getDocument();
}
}
// If targetObj has not been found there's a problem
return Base::Placement();
}
Base::Placement AssemblyObject::getGlobalPlacement(App::DocumentObject* targetObj,
App::PropertyXLinkSub* prop)
{
if (!targetObj || !prop) {
return Base::Placement();
}
std::vector<std::string> subs = prop->getSubValues();
if (subs.empty()) {
return Base::Placement();
}
return getGlobalPlacement(targetObj, prop->getValue(), subs[0]);
}
double AssemblyObject::getJointDistance(App::DocumentObject* joint)
{
double distance = 0.0;
@@ -2193,7 +2102,7 @@ std::vector<std::string> AssemblyObject::getSubAsList(App::PropertyXLinkSub* pro
return {};
}
return splitSubName(subs[0]);
return Base::Tools::splitSubName(subs[0]);
}
std::vector<std::string> AssemblyObject::getSubAsList(App::DocumentObject* obj, const char* pName)
@@ -2203,27 +2112,6 @@ std::vector<std::string> AssemblyObject::getSubAsList(App::DocumentObject* obj,
return getSubAsList(prop);
}
std::vector<std::string> AssemblyObject::splitSubName(const std::string& sub)
{
// Turns 'Part.Part001.Body.Pad.Edge1'
// Into ['Part', 'Part001','Body','Pad','Edge1']
std::vector<std::string> subNames;
std::string subName;
std::istringstream subNameStream(sub);
while (std::getline(subNameStream, subName, '.')) {
subNames.push_back(subName);
}
// Check if the last character of the input string is the delimiter.
// If so, add an empty string to the subNames vector.
// Because the last subname is the element name and can be empty.
if (!sub.empty() && sub.back() == '.') {
subNames.push_back(""); // Append empty string for trailing dot.
}
return subNames;
}
std::string AssemblyObject::getElementFromProp(App::DocumentObject* obj, const char* pName)
{
std::vector<std::string> names = getSubAsList(obj, pName);
@@ -2264,7 +2152,7 @@ App::DocumentObject* AssemblyObject::getObjFromRef(App::DocumentObject* obj, std
App::Document* doc = obj->getDocument();
std::vector<std::string> names = splitSubName(sub);
std::vector<std::string> names = Base::Tools::splitSubName(sub);
// Lambda function to check if the typeId is a BodySubObject
auto isBodySubObject = [](App::DocumentObject* obj) -> bool {
@@ -2306,7 +2194,7 @@ App::DocumentObject* AssemblyObject::getObjFromRef(App::DocumentObject* obj, std
return obj;
}
if (obj->isDerivedFrom<App::Part>() || isLinkGroup(obj)) {
if (obj->isDerivedFrom<App::Part>() || obj->isLinkGroup()) {
continue;
}
else if (obj->isDerivedFrom<PartDesign::Body>()) {
@@ -2316,7 +2204,7 @@ App::DocumentObject* AssemblyObject::getObjFromRef(App::DocumentObject* obj, std
// Primitive, fastener, gear, etc.
return obj;
}
else if (isLink(obj)) {
else if (obj->isLink()) {
App::DocumentObject* linked_obj = obj->getLinkedObject();
if (linked_obj->isDerivedFrom<PartDesign::Body>()) {
auto* retObj = handlePartDesignBody(linked_obj, it);
@@ -2370,7 +2258,7 @@ App::DocumentObject* AssemblyObject::getMovingPartFromRef(App::DocumentObject* o
App::Document* doc = obj->getDocument();
std::vector<std::string> names = splitSubName(sub);
std::vector<std::string> names = Base::Tools::splitSubName(sub);
names.insert(names.begin(), obj->getNameInDocument());
bool assemblyPassed = false;
@@ -2381,7 +2269,7 @@ App::DocumentObject* AssemblyObject::getMovingPartFromRef(App::DocumentObject* o
continue;
}
if (isLink(obj)) { // update the document if necessary for next object
if (obj->isLink()) { // update the document if necessary for next object
doc = obj->getLinkedObject()->getDocument();
}
@@ -2398,7 +2286,7 @@ App::DocumentObject* AssemblyObject::getMovingPartFromRef(App::DocumentObject* o
continue; // we ignore groups.
}
if (isLinkGroup(obj)) {
if (obj->isLinkGroup()) {
continue;
}

View File

@@ -280,14 +280,6 @@ public:
const char* propName);
static std::vector<std::string> getSubAsList(App::PropertyXLinkSub* prop);
static std::vector<std::string> getSubAsList(App::DocumentObject* joint, const char* propName);
static std::vector<std::string> splitSubName(const std::string& subName);
static Base::Placement getPlacementFromProp(App::DocumentObject* obj, const char* propName);
static Base::Placement getGlobalPlacement(App::DocumentObject* targetObj,
App::DocumentObject* rootObj,
const std::string& sub);
static Base::Placement getGlobalPlacement(App::DocumentObject* targetObj,
App::PropertyXLinkSub* prop);
};
// using AssemblyObjectPython = App::FeaturePythonT<AssemblyObject>;

View File

@@ -46,6 +46,8 @@
#include <App/DocumentObject.h>
#include <App/Part.h>
#include <Base/Tools.h>
#include <Gui/Application.h>
#include <Gui/BitmapFactory.h>
#include <Gui/CommandT.h>
@@ -618,7 +620,7 @@ bool ViewProviderAssembly::getSelectedObjectsWithinAssembly(bool addPreselection
std::vector<std::string> objsSubNames = selObj.getSubNames();
for (auto& subNamesStr : objsSubNames) {
std::vector<std::string> subNames = AssemblyObject::splitSubName(subNamesStr);
std::vector<std::string> subNames = Base::Tools::splitSubName(subNamesStr);
if (subNames.empty()) {
continue;
}
@@ -764,7 +766,7 @@ ViewProviderAssembly::DragMode ViewProviderAssembly::findDragMode()
const char* plcPropName = (pName == "Reference1") ? "Placement1" : "Placement2";
// jcsPlc is relative to the Object
jcsPlc = AssemblyObject::getPlacementFromProp(movingJoint, plcPropName);
jcsPlc = App::GeoFeature::getPlacementFromProp(movingJoint, plcPropName);
// Make jcsGlobalPlc relative to the origin of the doc
auto* ref =
@@ -773,7 +775,7 @@ ViewProviderAssembly::DragMode ViewProviderAssembly::findDragMode()
return DragMode::Translation;
}
auto* obj = assemblyPart->getObjFromRef(movingJoint, pName.c_str());
Base::Placement global_plc = AssemblyObject::getGlobalPlacement(obj, ref);
Base::Placement global_plc = App::GeoFeature::getGlobalPlacement(obj, ref);
jcsGlobalPlc = global_plc * jcsPlc;
// Add downstream parts so that they move together
@@ -920,7 +922,7 @@ void ViewProviderAssembly::initMoveDragger()
App::DocumentObject* part = docsToMove[0].obj;
draggerInitPlc =
AssemblyObject::getGlobalPlacement(part, docsToMove[0].rootObj, docsToMove[0].sub);
App::GeoFeature::getGlobalPlacement(part, docsToMove[0].rootObj, docsToMove[0].sub);
std::vector<App::DocumentObject*> listOfObjs;
std::vector<App::PropertyXLinkSub*> listOfRefs;
for (auto& movingObj : docsToMove) {
@@ -1130,11 +1132,11 @@ ViewProviderAssembly::getCenterOfBoundingBox(const std::vector<MovingObject>& mo
// bboxCenter does not take into account obj global placement
Base::Placement plc(bboxCenter, Base::Rotation());
// Change plc to be relative to the object placement.
Base::Placement objPlc = AssemblyObject::getPlacementFromProp(movingObj.obj, "Placement");
Base::Placement objPlc = App::GeoFeature::getPlacementFromProp(movingObj.obj, "Placement");
plc = objPlc.inverse() * plc;
// Change plc to be relative to the origin of the document.
Base::Placement global_plc =
AssemblyObject::getGlobalPlacement(movingObj.obj, movingObj.rootObj, movingObj.sub);
App::GeoFeature::getGlobalPlacement(movingObj.obj, movingObj.rootObj, movingObj.sub);
plc = global_plc * plc;
bboxCenter = plc.getPosition();