Assembly : Initial implementation of 'create joint' command.
This commit is contained in:
@@ -54,3 +54,185 @@ def isDocTemporary(doc):
|
||||
except AttributeError:
|
||||
temp = False
|
||||
return temp
|
||||
|
||||
|
||||
def getObject(full_name):
|
||||
# full_name is "Assembly.Assembly1.Assembly2.Assembly3.Box.Edge16"
|
||||
# or "Assembly.Assembly1.Assembly2.Assembly3.Body.pad.Edge16"
|
||||
# We want either Body or Box.
|
||||
parts = full_name.split(".")
|
||||
doc = App.ActiveDocument
|
||||
if len(parts) < 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(parts[-3]) # So either 'Body', or 'Assembly'
|
||||
|
||||
if not obj:
|
||||
return None
|
||||
|
||||
if obj.TypeId == "PartDesign::Body":
|
||||
return obj
|
||||
elif obj.TypeId == "App::Link":
|
||||
linked_obj = obj.getLinkedObject()
|
||||
if linked_obj.TypeId == "PartDesign::Body":
|
||||
return obj
|
||||
|
||||
else: # primitive, fastener, gear ... or link to primitive, fastener, gear...
|
||||
return doc.getObject(parts[-2])
|
||||
|
||||
|
||||
def getElementName(full_name):
|
||||
# full_name is "Assembly.Assembly1.Assembly2.Assembly3.Box.Edge16"
|
||||
# We want either Edge16.
|
||||
parts = full_name.split(".")
|
||||
|
||||
if len(parts) < 3:
|
||||
# At minimum "Assembly.Box.edge16". It shouldn't be shorter
|
||||
return ""
|
||||
|
||||
return parts[-1]
|
||||
|
||||
|
||||
def getObjsNamesAndElement(obj_name, sub_name):
|
||||
# if obj_name = "Assembly" and sub_name = "Assembly1.Assembly2.Assembly3.Box.Edge16"
|
||||
# this will return ["Assembly","Assembly1","Assembly2","Assembly3","Box"] and "Edge16"
|
||||
|
||||
parts = sub_name.split(".")
|
||||
|
||||
# The last part is always the element name even if empty
|
||||
element_name = parts[-1]
|
||||
|
||||
# The remaining parts are object names
|
||||
obj_names = parts[:-1]
|
||||
obj_names.insert(0, obj_name)
|
||||
|
||||
return obj_names, element_name
|
||||
|
||||
|
||||
def getFullObjName(obj_name, sub_name):
|
||||
# if obj_name = "Assembly" and sub_name = "Assembly1.Assembly2.Assembly3.Box.Edge16"
|
||||
# this will return "Assembly.Assembly1.Assembly2.Assembly3.Box"
|
||||
objs_names, element_name = getObjsNamesAndElement(obj_name, sub_name)
|
||||
return ".".join(objs_names)
|
||||
|
||||
|
||||
def getFullElementName(obj_name, sub_name):
|
||||
# if obj_name = "Assembly" and sub_name = "Assembly1.Assembly2.Assembly3.Box.Edge16"
|
||||
# this will return "Assembly.Assembly1.Assembly2.Assembly3.Box.Edge16"
|
||||
return obj_name + "." + sub_name
|
||||
|
||||
|
||||
def extract_type_and_number(element_name):
|
||||
element_type = ""
|
||||
element_number = ""
|
||||
|
||||
for char in element_name:
|
||||
if char.isalpha():
|
||||
# If the character is a letter, it's part of the type
|
||||
element_type += char
|
||||
elif char.isdigit():
|
||||
# If the character is a digit, it's part of the number
|
||||
element_number += char
|
||||
else:
|
||||
break
|
||||
|
||||
if element_type and element_number:
|
||||
element_number = int(element_number)
|
||||
return element_type, element_number
|
||||
else:
|
||||
return None, None
|
||||
|
||||
|
||||
def findElementClosestVertex(selection_dict):
|
||||
elt_type, elt_index = extract_type_and_number(selection_dict["element_name"])
|
||||
|
||||
if elt_type == "Vertex":
|
||||
return selection_dict["element_name"]
|
||||
|
||||
elif elt_type == "Edge":
|
||||
edge = selection_dict["object"].Shape.Edges[elt_index - 1]
|
||||
|
||||
curve = edge.Curve
|
||||
if curve.TypeId == "Part::GeomCircle":
|
||||
# For centers, as they are not shape vertexes, we return the element name.
|
||||
# For now we only allow selecting the center of arcs / circles.
|
||||
return selection_dict["element_name"]
|
||||
|
||||
edge_points = getPointsFromVertexes(edge.Vertexes)
|
||||
closest_vertex_index, _ = findClosestPointToMousePos(
|
||||
edge_points, selection_dict["mouse_pos"]
|
||||
)
|
||||
vertex_name = findVertexNameInObject(
|
||||
edge.Vertexes[closest_vertex_index], selection_dict["object"]
|
||||
)
|
||||
|
||||
return vertex_name
|
||||
|
||||
elif elt_type == "Face":
|
||||
face = selection_dict["object"].Shape.Faces[elt_index - 1]
|
||||
|
||||
# Handle the circle/arc edges for their centers
|
||||
center_points = []
|
||||
center_points_edge_indexes = []
|
||||
edges = face.Edges
|
||||
|
||||
for i, edge in enumerate(edges):
|
||||
curve = edge.Curve
|
||||
if curve.TypeId == "Part::GeomCircle":
|
||||
center_points.append(curve.Location)
|
||||
center_points_edge_indexes.append(i)
|
||||
|
||||
if len(center_points) > 0:
|
||||
closest_center_index, closest_center_distance = findClosestPointToMousePos(
|
||||
center_points, selection_dict["mouse_pos"]
|
||||
)
|
||||
|
||||
# Hendle the face vertexes
|
||||
face_points = getPointsFromVertexes(face.Vertexes)
|
||||
closest_vertex_index, closest_vertex_distance = findClosestPointToMousePos(
|
||||
face_points, selection_dict["mouse_pos"]
|
||||
)
|
||||
|
||||
if len(center_points) > 0:
|
||||
if closest_center_distance < closest_vertex_distance:
|
||||
# Note the index here is the index within the face! Not the object.
|
||||
index = center_points_edge_indexes[closest_center_index] + 1
|
||||
return "Edge" + str(index)
|
||||
|
||||
vertex_name = findVertexNameInObject(
|
||||
face.Vertexes[closest_vertex_index], selection_dict["object"]
|
||||
)
|
||||
|
||||
return vertex_name
|
||||
|
||||
return ""
|
||||
|
||||
|
||||
def getPointsFromVertexes(vertexes):
|
||||
points = []
|
||||
for vtx in vertexes:
|
||||
points.append(vtx.Point)
|
||||
return points
|
||||
|
||||
|
||||
def findClosestPointToMousePos(candidates_points, mousePos):
|
||||
closest_point_index = None
|
||||
point_min_length = None
|
||||
|
||||
for i, point in enumerate(candidates_points):
|
||||
length = (mousePos - point).Length
|
||||
if closest_point_index is None or length < point_min_length:
|
||||
closest_point_index = i
|
||||
point_min_length = length
|
||||
|
||||
return closest_point_index, point_min_length
|
||||
|
||||
|
||||
def findVertexNameInObject(vertex, obj):
|
||||
for i, vtx in enumerate(obj.Shape.Vertexes):
|
||||
if vtx.Point == vertex.Point:
|
||||
return "Vertex" + str(i + 1)
|
||||
return ""
|
||||
|
||||
Reference in New Issue
Block a user