Assembly: BOM: take mirrored state of links in account. (#26113)

This commit is contained in:
PaddleStroke
2026-02-10 16:10:03 +01:00
committed by GitHub
parent bf51a00dfd
commit 3d0df45cd4
2 changed files with 52 additions and 5 deletions

View File

@@ -32,6 +32,7 @@
#include <App/PropertyPythonObject.h>
#include <App/Range.h>
#include <Base/Console.h>
#include <Base/Parameter.h>
#include <Base/Placement.h>
#include <Base/Rotation.h>
#include <Base/Tools.h>
@@ -144,9 +145,15 @@ void BomObject::generateBOM()
saveCustomColumnData();
clearAll();
obj_list.clear();
obj_mirrored_list.clear();
size_t row = 0;
size_t col = 0;
auto hGrp = App::GetApplication().GetParameterGroupByPath(
"User parameter:BaseApp/Preferences/Mod/Assembly"
);
mirroredSuffix = hGrp->GetASCII("BomMirroredSuffix", " (mirrored)");
// Populate headers
for (auto& columnName : columnsNames.getValues()) {
setCell(App::CellAddress(row, col), columnName.c_str());
@@ -184,6 +191,9 @@ void BomObject::addObjectChildrenToBom(
if (!child) {
continue;
}
bool isMirrored = isObjMirrored(child);
if (auto* asmLink = freecad_cast<AssemblyLink*>(child)) {
child = asmLink->getLinkedAssembly();
if (!child) {
@@ -206,10 +216,14 @@ void BomObject::addObjectChildrenToBom(
// Check if the object is not already in (case of links). And if so just increment.
// Note: an object can be used in several parts. In which case we do no want to blindly
// increment.
// We also check if the Mirror state matches. Mirrored parts should not group with
// non-mirrored parts.
bool found = false;
for (size_t i = siblingsInitialRow; i <= row; ++i) {
size_t idInList = i - 1; // -1 for the header
if (idInList < obj_list.size() && child == obj_list[idInList]) {
if (idInList < obj_list.size() && child == obj_list[idInList]
&& idInList < obj_mirrored_list.size()
&& isMirrored == obj_mirrored_list[idInList]) {
int qty = std::stoi(getText(i, quantityColIndex)) + 1;
setCell(App::CellAddress(i, quantityColIndex), std::to_string(qty).c_str());
@@ -225,7 +239,7 @@ void BomObject::addObjectChildrenToBom(
std::string sub_index = index + std::to_string(sub_i);
++sub_i;
addObjectToBom(child, row, sub_index);
addObjectToBom(child, row, sub_index, isMirrored);
++row;
if ((child->isDerivedFrom<AssemblyObject>() && detailSubAssemblies.getValue())
@@ -236,7 +250,26 @@ void BomObject::addObjectChildrenToBom(
}
}
void BomObject::addObjectToBom(App::DocumentObject* obj, size_t row, std::string index)
bool BomObject::isObjMirrored(App::DocumentObject* obj)
{
// Determine mirror state based on Scale properties.
// We multiply scales to handle nested mirroring (e.g., Mirrored LinkElement inside Mirrored
// LinkGroup = Normal).
double accumulatedScale = 1.0;
if (auto element = static_cast<App::LinkElement*>(obj)) {
accumulatedScale *= element->Scale.getValue();
if (auto group = element->getLinkGroup()) {
accumulatedScale *= group->Scale.getValue();
}
}
else if (auto link = static_cast<App::Link*>(obj)) {
accumulatedScale *= link->Scale.getValue();
}
return accumulatedScale < 0.0;
}
void BomObject::addObjectToBom(App::DocumentObject* obj, size_t row, std::string index, bool isMirrored)
{
obj_list.push_back(obj);
size_t col = 0;
@@ -245,7 +278,17 @@ void BomObject::addObjectToBom(App::DocumentObject* obj, size_t row, std::string
setCell(App::CellAddress(row, col), (std::string("'") + index).c_str());
}
else if (columnName == "Name") {
setCell(App::CellAddress(row, col), obj->Label.getValue());
std::string name = obj->Label.getValue();
// Distinctly label mirrored parts so they are identifiable in the BOM
if (isMirrored) {
if (auto* linkedObj = obj->getLinkedObject()) {
// We add a suffix only if the label is the same.
if (name == linkedObj->Label.getValue()) {
name += mirroredSuffix;
}
}
}
setCell(App::CellAddress(row, col), name.c_str());
}
else if (columnName == "File Name") {
setCell(App::CellAddress(row, col), obj->getDocument()->getFileName());

View File

@@ -76,9 +76,10 @@ public:
App::DocumentObjectExecReturn* execute() override;
void generateBOM();
void addObjectToBom(App::DocumentObject* obj, size_t row, std::string index);
void addObjectToBom(App::DocumentObject* obj, size_t row, std::string index, bool isMirrored = false);
void addObjectChildrenToBom(std::vector<App::DocumentObject*> objs, size_t& row, std::string index);
void saveCustomColumnData();
bool isObjMirrored(App::DocumentObject* obj);
AssemblyObject* getAssembly() const;
@@ -93,9 +94,12 @@ public:
std::vector<BomDataElement> dataElements;
std::vector<App::DocumentObject*> obj_list;
std::vector<bool> obj_mirrored_list;
private:
std::string getBomPropertyValue(App::DocumentObject* obj, const std::string& baseName);
std::string mirroredSuffix;
};