Assembly: Add support to external objects. (And various fixes)
This commit is contained in:
@@ -27,6 +27,9 @@
|
||||
#include <BRepAdaptor_Surface.hxx>
|
||||
#include <TopoDS.hxx>
|
||||
#include <TopoDS_Face.hxx>
|
||||
#include <gp_Circ.hxx>
|
||||
#include <gp_Cylinder.hxx>
|
||||
#include <gp_Sphere.hxx>
|
||||
#include <cmath>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
@@ -36,6 +39,7 @@
|
||||
#include <App/Document.h>
|
||||
#include <App/DocumentObjectGroup.h>
|
||||
#include <App/FeaturePythonPyImp.h>
|
||||
#include <App/Link.h>
|
||||
#include <App/PropertyPythonObject.h>
|
||||
#include <Base/Console.h>
|
||||
#include <Base/Placement.h>
|
||||
@@ -444,8 +448,8 @@ std::shared_ptr<ASMTJoint> AssemblyObject::makeMbdJointDistanceEdgeEdge(App::Doc
|
||||
{
|
||||
const char* elt1 = getElementFromProp(joint, "Element1");
|
||||
const char* elt2 = getElementFromProp(joint, "Element2");
|
||||
auto* obj1 = getLinkedObjFromProp(joint, "Object1");
|
||||
auto* obj2 = getLinkedObjFromProp(joint, "Object2");
|
||||
auto* obj1 = getLinkedObjFromNameProp(joint, "Object1", "Part1");
|
||||
auto* obj2 = getLinkedObjFromNameProp(joint, "Object2", "Part2");
|
||||
|
||||
if (isEdgeType(obj1, elt1, GeomAbs_Line) || isEdgeType(obj2, elt2, GeomAbs_Line)) {
|
||||
if (!isEdgeType(obj1, elt1, GeomAbs_Line)) {
|
||||
@@ -492,8 +496,8 @@ std::shared_ptr<ASMTJoint> AssemblyObject::makeMbdJointDistanceFaceFace(App::Doc
|
||||
{
|
||||
const char* elt1 = getElementFromProp(joint, "Element1");
|
||||
const char* elt2 = getElementFromProp(joint, "Element2");
|
||||
auto* obj1 = getLinkedObjFromProp(joint, "Object1");
|
||||
auto* obj2 = getLinkedObjFromProp(joint, "Object2");
|
||||
auto* obj1 = getLinkedObjFromNameProp(joint, "Object1", "Part1");
|
||||
auto* obj2 = getLinkedObjFromNameProp(joint, "Object2", "Part2");
|
||||
|
||||
if (isFaceType(obj1, elt1, GeomAbs_Plane) || isFaceType(obj2, elt2, GeomAbs_Plane)) {
|
||||
if (!isFaceType(obj1, elt1, GeomAbs_Plane)) {
|
||||
@@ -623,7 +627,7 @@ std::shared_ptr<ASMTJoint>
|
||||
AssemblyObject::makeMbdJointDistanceFaceVertex(App::DocumentObject* joint)
|
||||
{
|
||||
const char* elt1 = getElementFromProp(joint, "Element1");
|
||||
auto* obj1 = getLinkedObjFromProp(joint, "Object1");
|
||||
auto* obj1 = getLinkedObjFromNameProp(joint, "Object1", "Part1");
|
||||
|
||||
if (isFaceType(obj1, elt1, GeomAbs_Plane)) {
|
||||
auto mbdJoint = CREATE<ASMTPointInPlaneJoint>::With();
|
||||
@@ -654,7 +658,7 @@ std::shared_ptr<ASMTJoint>
|
||||
AssemblyObject::makeMbdJointDistanceEdgeVertex(App::DocumentObject* joint)
|
||||
{
|
||||
const char* elt1 = getElementFromProp(joint, "Element1");
|
||||
auto* obj1 = getLinkedObjFromProp(joint, "Object1");
|
||||
auto* obj1 = getLinkedObjFromNameProp(joint, "Object1", "Part1");
|
||||
|
||||
if (isEdgeType(obj1, elt1, GeomAbs_Line)) { // Point on line joint.
|
||||
auto mbdJoint = CREATE<ASMTCylSphJoint>::With();
|
||||
@@ -676,7 +680,7 @@ AssemblyObject::makeMbdJointDistanceEdgeVertex(App::DocumentObject* joint)
|
||||
std::shared_ptr<ASMTJoint> AssemblyObject::makeMbdJointDistanceFaceEdge(App::DocumentObject* joint)
|
||||
{
|
||||
const char* elt2 = getElementFromProp(joint, "Element2");
|
||||
auto* obj2 = getLinkedObjFromProp(joint, "Object2");
|
||||
auto* obj2 = getLinkedObjFromNameProp(joint, "Object2", "Part2");
|
||||
|
||||
if (isEdgeType(obj2, elt2, GeomAbs_Line)) {
|
||||
// Make line in plane joint.
|
||||
@@ -705,16 +709,16 @@ AssemblyObject::makeMbdJoint(App::DocumentObject* joint)
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string fullMarkerName1 = handleOneSideOfJoint(joint, jointType, "Part1", "Placement1");
|
||||
std::string fullMarkerName2 = handleOneSideOfJoint(joint, jointType, "Part2", "Placement2");
|
||||
std::string fullMarkerName1 = handleOneSideOfJoint(joint, "Part1", "Placement1");
|
||||
std::string fullMarkerName2 = handleOneSideOfJoint(joint, "Part2", "Placement2");
|
||||
|
||||
mbdJoint->setMarkerI(fullMarkerName1);
|
||||
mbdJoint->setMarkerJ(fullMarkerName2);
|
||||
|
||||
return {mbdJoint};
|
||||
}
|
||||
|
||||
std::string AssemblyObject::handleOneSideOfJoint(App::DocumentObject* joint,
|
||||
JointType jointType,
|
||||
const char* propLinkName,
|
||||
const char* propPlcName)
|
||||
{
|
||||
@@ -843,10 +847,10 @@ void AssemblyObject::swapJCS(App::DocumentObject* joint)
|
||||
propPlacement1->setValue(propPlacement2->getValue());
|
||||
propPlacement2->setValue(temp);
|
||||
}
|
||||
auto propObject1 = dynamic_cast<App::PropertyLink*>(joint->getPropertyByName("Object1"));
|
||||
auto propObject2 = dynamic_cast<App::PropertyLink*>(joint->getPropertyByName("Object2"));
|
||||
auto propObject1 = dynamic_cast<App::PropertyString*>(joint->getPropertyByName("Object1"));
|
||||
auto propObject2 = dynamic_cast<App::PropertyString*>(joint->getPropertyByName("Object2"));
|
||||
if (propObject1 && propObject2) {
|
||||
auto temp = propObject1->getValue();
|
||||
auto temp = std::string(propObject1->getValue());
|
||||
propObject1->setValue(propObject2->getValue());
|
||||
propObject2->setValue(temp);
|
||||
}
|
||||
@@ -885,6 +889,10 @@ void AssemblyObject::savePlacementsForUndo()
|
||||
|
||||
void AssemblyObject::undoSolve()
|
||||
{
|
||||
if (previousPositions.size() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto& pair : previousPositions) {
|
||||
App::DocumentObject* obj = pair.first;
|
||||
if (!obj) {
|
||||
@@ -1004,7 +1012,7 @@ bool AssemblyObject::isFaceType(App::DocumentObject* obj,
|
||||
GeomAbs_SurfaceType type)
|
||||
{
|
||||
auto base = static_cast<PartApp::Feature*>(obj);
|
||||
const PartApp::TopoShape& TopShape = base->Shape.getShape();
|
||||
PartApp::TopoShape TopShape = base->Shape.getShape();
|
||||
|
||||
// Check for valid face types
|
||||
TopoDS_Face face = TopoDS::Face(TopShape.getSubShape(elName));
|
||||
@@ -1127,10 +1135,41 @@ App::DocumentObject* AssemblyObject::getLinkObjFromProp(App::DocumentObject* joi
|
||||
return propObj->getValue();
|
||||
}
|
||||
|
||||
App::DocumentObject* AssemblyObject::getLinkedObjFromProp(App::DocumentObject* joint,
|
||||
const char* propLinkName)
|
||||
App::DocumentObject* AssemblyObject::getLinkedObjFromNameProp(App::DocumentObject* joint,
|
||||
const char* pObjName,
|
||||
const char* pPart)
|
||||
{
|
||||
return getLinkObjFromProp(joint, propLinkName)->getLinkedObject(true);
|
||||
auto* propObjName = dynamic_cast<App::PropertyString*>(joint->getPropertyByName(pObjName));
|
||||
if (!propObjName) {
|
||||
return nullptr;
|
||||
}
|
||||
std::string objName = std::string(propObjName->getValue());
|
||||
|
||||
App::DocumentObject* containingPart = getLinkObjFromProp(joint, pPart);
|
||||
if (!containingPart) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (objName == containingPart->getNameInDocument()) {
|
||||
return containingPart->getLinkedObject(true);
|
||||
}
|
||||
|
||||
if (containingPart->getTypeId().isDerivedFrom(App::Link::getClassTypeId())) {
|
||||
App::Link* link = dynamic_cast<App::Link*>(containingPart);
|
||||
|
||||
containingPart = link->getLinkedObject(true);
|
||||
if (!containingPart) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto obj : containingPart->getOutList()) {
|
||||
if (objName == obj->getNameInDocument()) {
|
||||
return obj->getLinkedObject(true);
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Base::Placement AssemblyObject::getPlacementFromProp(App::DocumentObject* obj, const char* propName)
|
||||
|
||||
@@ -103,7 +103,6 @@ public:
|
||||
std::shared_ptr<MbD::ASMTJoint> makeMbdJointDistanceFaceFace(App::DocumentObject* joint);
|
||||
|
||||
std::string handleOneSideOfJoint(App::DocumentObject* joint,
|
||||
JointType jointType,
|
||||
const char* propObjLinkName,
|
||||
const char* propPlcName);
|
||||
void jointParts(std::vector<App::DocumentObject*> joints);
|
||||
@@ -144,7 +143,8 @@ public:
|
||||
std::string getElementTypeFromProp(App::DocumentObject* obj, const char* propName);
|
||||
Base::Placement getPlacementFromProp(App::DocumentObject* obj, const char* propName);
|
||||
App::DocumentObject* getLinkObjFromProp(App::DocumentObject* joint, const char* propName);
|
||||
App::DocumentObject* getLinkedObjFromProp(App::DocumentObject* joint, const char* propName);
|
||||
App::DocumentObject*
|
||||
getLinkedObjFromNameProp(App::DocumentObject* joint, const char* pObjName, const char* pPart);
|
||||
|
||||
private:
|
||||
std::shared_ptr<MbD::ASMTAssembly> mbdAssembly;
|
||||
|
||||
@@ -72,7 +72,8 @@ bool ViewProviderAssembly::doubleClicked()
|
||||
{
|
||||
if (isInEditMode()) {
|
||||
// Part is already 'Active' so we exit edit mode.
|
||||
Gui::Command::doCommand(Gui::Command::Gui, "Gui.activeDocument().resetEdit()");
|
||||
// Gui::Command::doCommand(Gui::Command::Gui, "Gui.activeDocument().resetEdit()");
|
||||
Gui::Application::Instance->activeDocument()->resetEdit();
|
||||
}
|
||||
else {
|
||||
// Part is not 'Active' so we enter edit mode to make it so.
|
||||
@@ -160,6 +161,16 @@ void ViewProviderAssembly::unsetEdit(int ModNum)
|
||||
partMoving = false;
|
||||
docsToMove = {};
|
||||
|
||||
// Check if the view is still active before trying to deactivate the assembly.
|
||||
auto activeDoc = Gui::Application::Instance->activeDocument();
|
||||
if (!activeDoc) {
|
||||
return;
|
||||
}
|
||||
auto activeView = activeDoc->getActiveView();
|
||||
if (!activeView) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the part as not 'Activated' ie not bold in the tree.
|
||||
Gui::Command::doCommand(Gui::Command::Gui,
|
||||
"Gui.ActiveDocument.ActiveView.setActiveObject('%s', None)",
|
||||
|
||||
@@ -40,6 +40,7 @@ __url__ = "https://www.freecad.org"
|
||||
|
||||
from pivy import coin
|
||||
import UtilsAssembly
|
||||
import Preferences
|
||||
|
||||
JointTypes = [
|
||||
QT_TRANSLATE_NOOP("AssemblyJoint", "Fixed"),
|
||||
@@ -73,6 +74,11 @@ JointUsingReverse = [
|
||||
]
|
||||
|
||||
|
||||
def solveIfAllowed(assembly, storePrev=False):
|
||||
if Preferences.preferences().GetBool("SolveInJointCreation", True):
|
||||
assembly.solve(storePrev)
|
||||
|
||||
|
||||
def flipPlacement(plc, localXAxis):
|
||||
flipRot = App.Rotation(localXAxis, 180)
|
||||
plc.Rotation = plc.Rotation.multiply(flipRot)
|
||||
@@ -96,10 +102,10 @@ class Joint:
|
||||
|
||||
# First Joint Connector
|
||||
joint.addProperty(
|
||||
"App::PropertyLink",
|
||||
"App::PropertyString", # Not PropertyLink because they don't support external objects
|
||||
"Object1",
|
||||
"Joint Connector 1",
|
||||
QT_TRANSLATE_NOOP("App::Property", "The first object of the joint"),
|
||||
QT_TRANSLATE_NOOP("App::Property", "The name of the first object of the joint"),
|
||||
)
|
||||
|
||||
joint.addProperty(
|
||||
@@ -133,12 +139,22 @@ class Joint:
|
||||
),
|
||||
)
|
||||
|
||||
joint.addProperty(
|
||||
"App::PropertyBool",
|
||||
"Detach1",
|
||||
"Joint Connector 1",
|
||||
QT_TRANSLATE_NOOP(
|
||||
"App::Property",
|
||||
"This prevent Placement1 from recomputing, enabling custom positioning of the placement.",
|
||||
),
|
||||
)
|
||||
|
||||
# Second Joint Connector
|
||||
joint.addProperty(
|
||||
"App::PropertyLink",
|
||||
"App::PropertyString",
|
||||
"Object2",
|
||||
"Joint Connector 2",
|
||||
QT_TRANSLATE_NOOP("App::Property", "The second object of the joint"),
|
||||
QT_TRANSLATE_NOOP("App::Property", "The name of the second object of the joint"),
|
||||
)
|
||||
|
||||
joint.addProperty(
|
||||
@@ -172,6 +188,16 @@ class Joint:
|
||||
),
|
||||
)
|
||||
|
||||
joint.addProperty(
|
||||
"App::PropertyBool",
|
||||
"Detach2",
|
||||
"Joint Connector 2",
|
||||
QT_TRANSLATE_NOOP(
|
||||
"App::Property",
|
||||
"This prevent Placement2 from recomputing, enabling custom positioning of the placement.",
|
||||
),
|
||||
)
|
||||
|
||||
joint.addProperty(
|
||||
"App::PropertyFloat",
|
||||
"Distance",
|
||||
@@ -236,7 +262,7 @@ class Joint:
|
||||
if hasattr(
|
||||
joint, "Vertex1"
|
||||
): # during loading the onchanged may be triggered before full init.
|
||||
self.getAssembly(joint).solve()
|
||||
solveIfAllowed(self.getAssembly(joint))
|
||||
|
||||
def execute(self, fp):
|
||||
"""Do something when doing a recomputation, this method is mandatory"""
|
||||
@@ -251,7 +277,7 @@ class Joint:
|
||||
joint.Part1 = None
|
||||
joint.FirstPartConnected = assembly.isPartConnected(current_selection[0]["part"])
|
||||
|
||||
joint.Object1 = current_selection[0]["object"]
|
||||
joint.Object1 = current_selection[0]["object"].Name
|
||||
joint.Part1 = current_selection[0]["part"]
|
||||
joint.Element1 = current_selection[0]["element_name"]
|
||||
joint.Vertex1 = current_selection[0]["vertex_name"]
|
||||
@@ -259,24 +285,24 @@ class Joint:
|
||||
joint, joint.Object1, joint.Part1, joint.Element1, joint.Vertex1
|
||||
)
|
||||
else:
|
||||
joint.Object1 = None
|
||||
joint.Object1 = ""
|
||||
joint.Part1 = None
|
||||
joint.Element1 = ""
|
||||
joint.Vertex1 = ""
|
||||
joint.Placement1 = App.Placement()
|
||||
|
||||
if len(current_selection) >= 2:
|
||||
joint.Object2 = current_selection[1]["object"]
|
||||
joint.Object2 = current_selection[1]["object"].Name
|
||||
joint.Part2 = current_selection[1]["part"]
|
||||
joint.Element2 = current_selection[1]["element_name"]
|
||||
joint.Vertex2 = current_selection[1]["vertex_name"]
|
||||
joint.Placement2 = self.findPlacement(
|
||||
joint, joint.Object2, joint.Part2, joint.Element2, joint.Vertex2, True
|
||||
)
|
||||
assembly.solve(True)
|
||||
solveIfAllowed(assembly, True)
|
||||
|
||||
else:
|
||||
joint.Object2 = None
|
||||
joint.Object2 = ""
|
||||
joint.Part2 = None
|
||||
joint.Element2 = ""
|
||||
joint.Vertex2 = ""
|
||||
@@ -284,12 +310,15 @@ class Joint:
|
||||
assembly.undoSolve()
|
||||
|
||||
def updateJCSPlacements(self, joint):
|
||||
joint.Placement1 = self.findPlacement(
|
||||
joint, joint.Object1, joint.Part1, joint.Element1, joint.Vertex1
|
||||
)
|
||||
joint.Placement2 = self.findPlacement(
|
||||
joint, joint.Object2, joint.Part2, joint.Element2, joint.Vertex2, True
|
||||
)
|
||||
if not joint.Detach1:
|
||||
joint.Placement1 = self.findPlacement(
|
||||
joint, joint.Object1, joint.Part1, joint.Element1, joint.Vertex1
|
||||
)
|
||||
|
||||
if not joint.Detach2:
|
||||
joint.Placement2 = self.findPlacement(
|
||||
joint, joint.Object2, joint.Part2, joint.Element2, joint.Vertex2, True
|
||||
)
|
||||
|
||||
"""
|
||||
So here we want to find a placement that corresponds to a local coordinate system that would be placed at the selected vertex.
|
||||
@@ -301,7 +330,11 @@ class Joint:
|
||||
- if elt is a cylindrical face, vtx can also be the center of the arcs of the cylindrical face.
|
||||
"""
|
||||
|
||||
def findPlacement(self, joint, obj, part, elt, vtx, isSecond=False):
|
||||
def findPlacement(self, joint, objName, part, elt, vtx, isSecond=False):
|
||||
if not objName or not part:
|
||||
return App.Placement()
|
||||
|
||||
obj = UtilsAssembly.getObjectInPart(objName, part)
|
||||
assembly = self.getAssembly(joint)
|
||||
plc = App.Placement()
|
||||
|
||||
@@ -430,7 +463,8 @@ class Joint:
|
||||
plc = joint.Part1.Placement.inverse() * joint.Placement1
|
||||
localXAxis = plc.Rotation.multVec(App.Vector(1, 0, 0))
|
||||
joint.Part1.Placement = flipPlacement(joint.Part1.Placement, localXAxis)
|
||||
self.getAssembly(joint).solve()
|
||||
|
||||
solveIfAllowed(self.getAssembly(joint))
|
||||
|
||||
def findCylindersIntersection(self, obj, surface, edge, elt_index):
|
||||
for j, facej in enumerate(obj.Shape.Faces):
|
||||
@@ -887,7 +921,7 @@ class TaskAssemblyCreateJoint(QtCore.QObject):
|
||||
|
||||
self.deactivate()
|
||||
|
||||
self.assembly.solve()
|
||||
solveIfAllowed(self.assembly)
|
||||
|
||||
App.closeActiveTransaction()
|
||||
return True
|
||||
@@ -974,15 +1008,18 @@ class TaskAssemblyCreateJoint(QtCore.QObject):
|
||||
self.current_selection = []
|
||||
self.preselection_dict = None
|
||||
|
||||
obj1 = UtilsAssembly.getObjectInPart(self.joint.Object1, self.joint.Part1)
|
||||
obj2 = UtilsAssembly.getObjectInPart(self.joint.Object2, self.joint.Part2)
|
||||
|
||||
selection_dict1 = {
|
||||
"object": self.joint.Object1,
|
||||
"object": obj1,
|
||||
"part": self.joint.Part1,
|
||||
"element_name": self.joint.Element1,
|
||||
"vertex_name": self.joint.Vertex1,
|
||||
}
|
||||
|
||||
selection_dict2 = {
|
||||
"object": self.joint.Object2,
|
||||
"object": obj2,
|
||||
"part": self.joint.Part2,
|
||||
"element_name": self.joint.Element2,
|
||||
"vertex_name": self.joint.Vertex2,
|
||||
@@ -991,14 +1028,15 @@ class TaskAssemblyCreateJoint(QtCore.QObject):
|
||||
self.current_selection.append(selection_dict1)
|
||||
self.current_selection.append(selection_dict2)
|
||||
|
||||
elName = self.getObjSubNameFromObj(self.joint.Object1, self.joint.Element1)
|
||||
"""print(
|
||||
f"Gui.Selection.addSelection('{self.doc.Name}', '{self.joint.Object1.Name}', '{elName}')"
|
||||
)"""
|
||||
Gui.Selection.addSelection(self.doc.Name, self.joint.Object1.Name, elName)
|
||||
elName = self.getObjSubNameFromObj(obj1, self.joint.Element1)
|
||||
if obj1 != self.joint.Part1:
|
||||
elName = obj1.Name + "." + elName
|
||||
Gui.Selection.addSelection(self.doc.Name, self.joint.Part1.Name, elName)
|
||||
|
||||
elName = self.getObjSubNameFromObj(self.joint.Object2, self.joint.Element2)
|
||||
Gui.Selection.addSelection(self.doc.Name, self.joint.Object2.Name, elName)
|
||||
elName = self.getObjSubNameFromObj(obj2, self.joint.Element2)
|
||||
if obj2 != self.joint.Part2:
|
||||
elName = obj2.Name + "." + elName
|
||||
Gui.Selection.addSelection(self.doc.Name, self.joint.Part2.Name, elName)
|
||||
|
||||
self.form.distanceSpinbox.setProperty("rawValue", self.joint.Distance)
|
||||
self.form.offsetSpinbox.setProperty("rawValue", self.joint.Offset.z)
|
||||
@@ -1033,7 +1071,6 @@ class TaskAssemblyCreateJoint(QtCore.QObject):
|
||||
self.form.featureList.clear()
|
||||
simplified_names = []
|
||||
for sel in self.current_selection:
|
||||
# TODO: ideally we probably want to hide the feature name in case of PartDesign bodies. ie body.face12 and not body.pad2.face12
|
||||
sname = sel["object"].Label
|
||||
if sel["element_name"] != "":
|
||||
sname = sname + "." + sel["element_name"]
|
||||
@@ -1076,7 +1113,7 @@ class TaskAssemblyCreateJoint(QtCore.QObject):
|
||||
|
||||
placement = self.joint.Proxy.findPlacement(
|
||||
self.joint,
|
||||
self.preselection_dict["object"],
|
||||
self.preselection_dict["object"].Name,
|
||||
self.preselection_dict["part"],
|
||||
self.preselection_dict["element_name"],
|
||||
self.preselection_dict["vertex_name"],
|
||||
|
||||
@@ -90,43 +90,82 @@ def assembly_has_at_least_n_parts(n):
|
||||
|
||||
|
||||
def getObject(full_name):
|
||||
# full_name is "Assembly.Assembly1.LinkOrPart1.Box.Edge16"
|
||||
# or "Assembly.Assembly1.LinkOrPart1.Body.pad.Edge16"
|
||||
# or "Assembly.Assembly1.LinkOrPart1.Body.Local_CS.X"
|
||||
# We want either Body or Box or Local_CS.
|
||||
# full_name is "Assembly.LinkOrAssembly1.LinkOrPart1.LinkOrBox.Edge16"
|
||||
# or "Assembly.LinkOrAssembly1.LinkOrPart1.LinkOrBody.pad.Edge16"
|
||||
# or "Assembly.LinkOrAssembly1.LinkOrPart1.LinkOrBody.Local_CS.X"
|
||||
# We want either LinkOrBody or LinkOrBox or Local_CS.
|
||||
names = full_name.split(".")
|
||||
doc = App.ActiveDocument
|
||||
|
||||
if len(names) < 3:
|
||||
App.Console.PrintError(
|
||||
"getObject() in UtilsAssembly.py the object name is too short, at minimum it should be something like 'Assembly.Box.edge16'. It shouldn't be shorter"
|
||||
)
|
||||
return None
|
||||
|
||||
obj = doc.getObject(names[-2])
|
||||
prevObj = None
|
||||
|
||||
if obj and obj.TypeId == "PartDesign::CoordinateSystem":
|
||||
return doc.getObject(names[-2])
|
||||
for i, objName in enumerate(names):
|
||||
if i == 0:
|
||||
prevObj = doc.getObject(objName)
|
||||
if prevObj.TypeId == "App::Link":
|
||||
prevObj = prevObj.getLinkedObject()
|
||||
continue
|
||||
|
||||
obj = doc.getObject(names[-3]) # So either 'Body', or 'Assembly'
|
||||
obj = None
|
||||
if prevObj.TypeId in {"App::Part", "Assembly::AssemblyObject", "App::DocumentObjectGroup"}:
|
||||
for obji in prevObj.OutList:
|
||||
if obji.Name == objName:
|
||||
obj = obji
|
||||
break
|
||||
|
||||
if not obj:
|
||||
return None
|
||||
if obj is None:
|
||||
return None
|
||||
|
||||
if obj.TypeId == "PartDesign::Body":
|
||||
return obj
|
||||
elif obj.TypeId == "App::Link":
|
||||
linked_obj = obj.getLinkedObject()
|
||||
if linked_obj.TypeId == "PartDesign::Body":
|
||||
# the last is the element name. So if we are at the last but one name, then it must be the selected
|
||||
if i == len(names) - 2:
|
||||
return obj
|
||||
|
||||
# primitive, fastener, gear ... or link to primitive, fastener, gear...
|
||||
return doc.getObject(names[-2])
|
||||
if obj.TypeId == "App::Link":
|
||||
linked_obj = obj.getLinkedObject()
|
||||
if linked_obj.TypeId == "PartDesign::Body":
|
||||
if i + 1 < len(names):
|
||||
obj2 = doc.getObject(names[i + 1])
|
||||
if obj2 and obj2.TypeId == "PartDesign::CoordinateSystem":
|
||||
return obj2
|
||||
return obj
|
||||
elif linked_obj.isDerivedFrom("Part::Feature"):
|
||||
return obj
|
||||
else:
|
||||
prevObj = linked_obj
|
||||
continue
|
||||
|
||||
elif obj.TypeId in {"App::Part", "Assembly::AssemblyObject", "App::DocumentObjectGroup"}:
|
||||
prevObj = obj
|
||||
continue
|
||||
|
||||
elif obj.TypeId == "PartDesign::Body":
|
||||
if i + 1 < len(names):
|
||||
obj2 = doc.getObject(names[i + 1])
|
||||
if obj2 and obj2.TypeId == "PartDesign::CoordinateSystem":
|
||||
return obj2
|
||||
return obj
|
||||
|
||||
elif obj.isDerivedFrom("Part::Feature"):
|
||||
# primitive, fastener, gear ...
|
||||
return obj
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def getContainingPart(full_name, selected_object):
|
||||
# full_name is "Assembly.Assembly1.LinkOrPart1.Box.Edge16"
|
||||
# or "Assembly.Assembly1.LinkOrPart1.Body.pad.Edge16"
|
||||
# We want either Body or Box.
|
||||
if selected_object is None:
|
||||
App.Console.PrintError("getContainingPart() in UtilsAssembly.py selected_object is None")
|
||||
return None
|
||||
|
||||
names = full_name.split(".")
|
||||
doc = App.ActiveDocument
|
||||
if len(names) < 3:
|
||||
@@ -141,6 +180,9 @@ def getContainingPart(full_name, selected_object):
|
||||
if not obj:
|
||||
continue
|
||||
|
||||
if obj == selected_object:
|
||||
return selected_object
|
||||
|
||||
if (
|
||||
obj.TypeId == "PartDesign::Body"
|
||||
and selected_object.TypeId == "PartDesign::CoordinateSystem"
|
||||
@@ -156,6 +198,8 @@ def getContainingPart(full_name, selected_object):
|
||||
elif obj.TypeId == "App::Link":
|
||||
linked_obj = obj.getLinkedObject()
|
||||
if linked_obj.TypeId == "App::Part":
|
||||
# linked_obj_doc = linked_obj.Document
|
||||
# selected_obj_in_doc = doc.getObject(selected_object.Name)
|
||||
if linked_obj.hasObject(selected_object, True):
|
||||
return obj
|
||||
|
||||
@@ -163,6 +207,21 @@ def getContainingPart(full_name, selected_object):
|
||||
return selected_object
|
||||
|
||||
|
||||
def getObjectInPart(objName, part):
|
||||
if part.Name == objName:
|
||||
return part
|
||||
|
||||
if part.TypeId == "App::Link":
|
||||
part = part.getLinkedObject()
|
||||
|
||||
if part.TypeId in {"App::Part", "Assembly::AssemblyObject", "App::DocumentObjectGroup"}:
|
||||
for obji in part.OutList:
|
||||
if obji.Name == objName:
|
||||
return obji
|
||||
|
||||
return None
|
||||
|
||||
|
||||
# The container is used to support cases where the same object appears at several places
|
||||
# which happens when you have a link to a part.
|
||||
def getGlobalPlacement(targetObj, container=None):
|
||||
|
||||
Reference in New Issue
Block a user