ModelHandle/tools/step_service/freecad_trim_step.py

97 lines
3.5 KiB
Python

import json
import sys
def get_script_arguments(argv):
if "--pass" in argv:
pass_index = argv.index("--pass")
script_args = argv[pass_index + 1 :]
else:
script_args = argv[2:]
if len(script_args) < 3:
raise ValueError("Expected input path, deleted paths manifest, and output path.")
return script_args[0], script_args[1], script_args[2]
def should_include_in_tree(document_object):
type_id = getattr(document_object, "TypeId", "")
return type_id not in {"App::Origin", "App::Line", "App::Plane", "Part::Feature"}
def get_tree_children(objects):
filtered_objects = [document_object for document_object in objects if should_include_in_tree(document_object)]
def sort_key(document_object):
child_count = len(get_tree_children(list(getattr(document_object, "OutList", []))))
is_leaf_part = child_count == 0
return (1 if is_leaf_part else 0)
filtered_objects.sort(key=sort_key)
return filtered_objects
def enumerate_objects(objects, parent_path=""):
filtered_objects = get_tree_children(objects)
for index, document_object in enumerate(filtered_objects):
object_path = str(index) if parent_path == "" else parent_path + "/" + str(index)
yield object_path, document_object
child_objects = list(getattr(document_object, "OutList", []))
yield from enumerate_objects(child_objects, object_path)
def collect_subtree_objects(objects, target_path, parent_path=""):
collected_objects = []
filtered_objects = get_tree_children(objects)
for index, document_object in enumerate(filtered_objects):
object_path = str(index) if parent_path == "" else parent_path + "/" + str(index)
child_objects = list(getattr(document_object, "OutList", []))
if target_path is None:
collected_objects.append(document_object)
collected_objects.extend(collect_subtree_objects(child_objects, None, object_path))
elif object_path == target_path:
collected_objects.append(document_object)
collected_objects.extend(collect_subtree_objects(child_objects, None, object_path))
elif target_path.startswith(object_path + "/"):
collected_objects.extend(collect_subtree_objects(child_objects, target_path, object_path))
return collected_objects
def main():
input_path, deleted_paths_path, output_path = get_script_arguments(sys.argv)
with open(deleted_paths_path, "r", encoding="utf-8") as deleted_file:
deleted_paths = set(json.load(deleted_file))
import FreeCAD
import Import
document = FreeCAD.newDocument("TrimmedStep")
Import.insert(input_path, document.Name)
objects_to_delete = []
root_objects = list(document.RootObjects)
for deleted_path in deleted_paths:
objects_to_delete.extend(collect_subtree_objects(root_objects, deleted_path))
unique_objects = []
seen_names = set()
for document_object in objects_to_delete:
object_name = getattr(document_object, "Name", None)
if object_name is None or object_name in seen_names:
continue
seen_names.add(object_name)
unique_objects.append(document_object)
unique_objects.sort(key=lambda document_object: len(list(getattr(document_object, "OutListRecursive", []))), reverse=True)
for document_object in unique_objects:
document.removeObject(document_object.Name)
Import.export(list(document.RootObjects), output_path)
FreeCAD.closeDocument(document.Name)
if __name__ in ("__main__", "freecad_trim_step"):
main()