Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-11-09 10:47:17

0001 import Mesh
0002 import FreeCAD as App
0003 import Part
0004 import os
0005 import sys
0006 
0007 freecad_file = ""
0008 
0009 def get_global_placement(obj): #this method I created with chatgpt

0010     """

0011     Calculate the global placement of a given object by considering its parent hierarchy.

0012 

0013     Parameters:

0014     obj (FreeCAD object): The object for which the global placement is calculated.

0015 

0016     Returns:

0017     FreeCAD.Placement: The global placement of the object.

0018     """
0019     # Initialize global placement with the object's own placement

0020     global_placement = obj.Placement
0021 
0022     # Traverse up the hierarchy

0023     while obj.InList:
0024         # Assume single parent scenario

0025         parent = obj.InList[0]
0026 
0027         # Multiply the current global placement by the parent's placement

0028         global_placement = parent.Placement.multiply(global_placement)
0029 
0030         # Move to the next parent

0031         obj = parent
0032 
0033     return global_placement
0034 
0035 def export_component_as_mesh(component, filename, tessellation_level = 0.1): #filename must contain .stl extension

0036     # Ensure the filename ends with .stl

0037     if not filename.lower().endswith(".stl"):
0038         raise ValueError("Filename must have a .stl extension")
0039     
0040     # Get the shape from the component

0041     shape = component.Shape
0042 
0043     # Apply the component's placement to transform it to the global coordinate system (THIS PART IS VERY IMPORTANT)

0044     #placement = component.Placement

0045     placement = get_global_placement(component)
0046     transformed_shape = shape.copy()
0047     transformed_shape.Placement = placement
0048     
0049     # Check if the shape is valid

0050     if shape.isNull():
0051         raise ValueError("Shape is null or invalid")
0052     
0053     # Recursion Case

0054     
0055     # Base Case

0056     # Tessellate the shape

0057     try:
0058         mesh_data = transformed_shape.tessellate(tessellation_level)
0059     except Exception as e:
0060         raise RuntimeError(f"Failed to tessellate shape: {e}")
0061 
0062     # Check if tessellation produced a valid mesh

0063     if not mesh_data or len(mesh_data) == 0:
0064         raise RuntimeError("Tessellation resulted in an empty mesh")
0065 
0066     # Create a Mesh::Feature object and set its mesh

0067     mesh_obj = App.ActiveDocument.addObject("Mesh::Feature", "Mesh")
0068     mesh_obj.Mesh = Mesh.Mesh(mesh_data)
0069     
0070     # Save the mesh as an STL file

0071     global freecad_file
0072     dir_path = os.path.splitext(freecad_file)[0] #remove the freecad extension from the freecad filename

0073     dir_path += "/"
0074     # Check if the directory exists

0075     if not os.path.exists(dir_path):
0076         try:
0077             # Create the directory

0078             os.makedirs(dir_path, exist_ok=True)
0079             print(f"Directory '{dir_path}' created successfully.")
0080         except OSError as e:
0081             print(f"Error creating directory: {e}")
0082     try:
0083         mesh_obj.Mesh.write(dir_path + filename)
0084         print(f"Mesh saved as {filename}")
0085     except Exception as e:
0086         raise RuntimeError(f"Failed to write STL file: {e}")
0087 
0088 
0089 def process_component(doc, component, parent_placement=App.Placement(), default_name = "unnamed_mesh"):
0090     if component.Label:
0091         name = component.Label
0092     else:
0093         name = default_name
0094     #note, given name is the name passed above from recursion

0095     print(f"Processing Component: {component.Name} (Label: {component.Label})")
0096     #If the component is a basic component (e.g., a "Part::Feature" or "PartDesign::Body"), transform it

0097     if component.TypeId in ["Part::Feature"]:
0098         export_component_as_mesh(component, name  + ".stl")
0099 
0100 # Main function to process all components in the document

0101 def transform_all_components_to_global(doc):
0102     components = [obj for obj in doc.Objects if obj.TypeId in ["Part::Feature"]]
0103     print(f"{len(components)} bodies found.")
0104     for component in components:
0105         process_component(doc, component)
0106         
0107 # Run the script

0108 
0109 # Load the FreeCAD file, the directory is the first argument of the script

0110 if len(sys.argv) < 2:
0111         print("Usage: python refine_step_for_ePIC.py <arg1> where <arg1> is the name of the FreeCAD(.FCStd) file.")
0112         sys.exit(1)
0113 freecad_file = str(sys.argv[2])
0114 print(freecad_file)
0115 doc = App.openDocument(freecad_file)
0116 print("dbg")
0117 if doc is None:
0118     print("File: " + freecad_file + " not found!!")
0119 transform_all_components_to_global(doc)
0120 # Optionally, close the document

0121 App.closeDocument(doc.Name)