ModelHandle/tools/step_service/freecad_trim_step.py
sladro 16a2e43649
Some checks failed
Build / build (18.x, macos-latest) (push) Has been cancelled
Build / build (18.x, ubuntu-latest) (push) Has been cancelled
Build / build (18.x, windows-latest) (push) Has been cancelled
Build / build (20.x, macos-latest) (push) Has been cancelled
Build / build (20.x, ubuntu-latest) (push) Has been cancelled
Build / build (20.x, windows-latest) (push) Has been cancelled
fix step save flow and add portable backend runtime support
2026-04-13 15:16:30 +08:00

113 lines
4.1 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_all_subtree_objects(objects):
collected_objects = []
for document_object in objects:
collected_objects.append(document_object)
child_objects = list(getattr(document_object, "OutList", []))
collected_objects.extend(collect_all_subtree_objects(child_objects))
return collected_objects
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_all_subtree_objects(child_objects))
elif object_path == target_path:
collected_objects.append(document_object)
collected_objects.extend(collect_all_subtree_objects(child_objects))
elif target_path.startswith(object_path + "/"):
collected_objects.extend(collect_subtree_objects(child_objects, target_path, object_path))
return collected_objects
def build_removal_names(objects_to_delete):
removal_candidates = []
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)
subtree_depth = len(list(getattr(document_object, "OutListRecursive", [])))
removal_candidates.append((object_name, subtree_depth))
removal_candidates.sort(key=lambda candidate: candidate[1], reverse=True)
return [object_name for object_name, _depth in removal_candidates]
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))
for object_name in build_removal_names(objects_to_delete):
if document.getObject(object_name) is None:
continue
document.removeObject(object_name)
Import.export(list(document.RootObjects), output_path)
FreeCAD.closeDocument(document.Name)
if __name__ in ("__main__", "freecad_trim_step"):
main()