import os import glob import json import numpy as np from OCC.Core.BRepCheck import BRepCheck_Analyzer from OCC.Extend.DataExchange import read_step_file, write_step_file import argparse import sys sys.path.append(".") from lib.visualize import vec2CADsolid, create_CAD from lib.curves import Line, Arc, Circle # Curves def add_line(start, end): start = np.array(start) end = np.array(end) return Line(start, end) def find_circle_center_and_radius(start_point, end_point, mid_point): # Convert points to numpy arrays start_point = np.array(start_point) end_point = np.array(end_point) mid_point = np.array(mid_point) # Calculate midpoints of the chords mid_point_start_end = (start_point + end_point) / 2 mid_point_start_mid = (start_point + mid_point) / 2 # Calculate direction vectors of the chords direction_start_end = end_point - start_point direction_start_mid = mid_point - start_point # Calculate perpendicular direction vectors perp_start_end = np.array([-direction_start_end[1], direction_start_end[0]]) perp_start_mid = np.array([-direction_start_mid[1], direction_start_mid[0]]) # Solve for the intersection of the perpendicular bisectors A = np.array([perp_start_end, -perp_start_mid]).T b = mid_point_start_mid - mid_point_start_end # Solve the linear system t, s = np.linalg.solve(A, b) # Calculate the center center = mid_point_start_end + t * perp_start_end # Calculate the radius radius = np.linalg.norm(center - start_point) return center, radius from lib.math_utils import angle_from_vector_to_x def add_arc(start, end, mid): # get radius and center point center, radius = find_circle_center_and_radius(start, end, mid) start = np.array(start) end = np.array(end) mid = np.array(mid) def get_angles_counterclockwise(eps=1e-8): c2s_vec = (start - center) / (np.linalg.norm(start - center) + eps) c2m_vec = (mid - center) / (np.linalg.norm(mid - center) + eps) c2e_vec = (end - center) / (np.linalg.norm(end - center) + eps) angle_s, angle_m, angle_e = angle_from_vector_to_x(c2s_vec), angle_from_vector_to_x(c2m_vec), \ angle_from_vector_to_x(c2e_vec) angle_s, angle_e = min(angle_s, angle_e), max(angle_s, angle_e) if not angle_s < angle_m < angle_e: angle_s, angle_e = angle_e - np.pi * 2, angle_s return angle_s, angle_e angle_s, angle_e = get_angles_counterclockwise() return Arc(start, end, center, radius, start_angle=angle_s, end_angle=angle_e, mid_point=mid) def add_circle(center, radius): center = np.array(center) return Circle(center, radius) from lib.sketch import Loop, Profile # Loops def add_loop(curves): res = Loop(curves) res.reorder() def autofix(loop): if len(loop.children) <= 1: return if isinstance(loop.children[0], Circle): return for i in range(0, len(loop.children) - 1): if not np.allclose(loop.children[i].end_point, loop.children[i+1].start_point): loop.children[i+1].start_point = loop.children[i].end_point print("warning: fixing loop") if not np.allclose(loop.children[len(loop.children) - 1].end_point, loop.children[0].start_point): loop.children[len(loop.children) - 1].start_point = loop.children[0].end_point print("warning: fixing loop") autofix(res) return res # Sketch-Profile def add_profile(loops): return Profile(loops) from lib.extrude import CoordSystem, Extrude, CADSequence from lib.math_utils import polar_parameterization def find_n_from_x_and_y(x, y): """ Given vectors x and y, find a vector n such that y = n × x. Assumes that n is orthogonal to x. Parameters: x (numpy array): The vector x. y (numpy array): The vector y. Returns: numpy array: The vector n. """ # Step 1: Compute the cross product of x and y to get n' n_prime = np.cross(x, y) # Step 2: Normalize n' to get the unit vector n_prime_unit = n_prime / np.linalg.norm(n_prime) # Step 3: Determine the correct sign of n_prime_unit # To ensure y = n × x, we should check if the direction is correct if np.allclose(np.cross(n_prime_unit, x), y): n = n_prime_unit else: n = -n_prime_unit return n def add_sketchplane(origin, normal, x_axis, y_axis): origin = np.array(origin) normal = np.array(normal) x_axis = np.array(x_axis) y_axis = np.array(y_axis) #print(y_axis) normal_axis = find_n_from_x_and_y(x_axis, y_axis) # get theta and phi theta, phi, gamma = polar_parameterization(normal_axis, x_axis) #print(normal_axis, x_axis) #print(theta, phi, gamma) return CoordSystem(origin, theta, phi, gamma) class Sketch(object): def __init__(self, sketch_plane, profile, sketch_position, sketch_size): self.sketch_plane = sketch_plane self.profile = profile self.sketch_position = sketch_position self.sketch_size = sketch_size def add_sketch(sketch_plane, profile, sketch_position=[0.0,0.0,0.0], sketch_size=0): return Sketch(sketch_plane, profile, np.array(sketch_position), sketch_size) cad_seq = [] def add_extrude(sketch: Sketch, operation, type, extent_one, extent_two): res = Extrude( sketch.profile, sketch.sketch_plane, np.intc(operation), np.intc(type), np.double(extent_one), np.double(extent_two), np.double(sketch.sketch_position), np.double(sketch.sketch_size) ) cad_seq.append(res) return res def _process(path, path_o): global cad_seq cad_seq.clear() with open(path, 'r') as file: code = file.read() # 执行读取到的代码 exec(code) cad = CADSequence(cad_seq) #print(cad) out_shape = create_CAD(cad) write_step_file(out_shape, path_o) error_list = [] from lib.file_utils import ensure_dir parser = argparse.ArgumentParser() parser.add_argument('--src', type=str, required=True, help="source folder") parser.add_argument('-o', '--outputs', type=str, default=None, help="save folder") args = parser.parse_args() src_dir = args.src print(src_dir) out_paths = sorted(glob.glob(os.path.join(src_dir, "*.{}".format("py")))) save_dir = args.src + "_step" if args.outputs is None else args.outputs ensure_dir(save_dir) import traceback for path in out_paths: name = path.split("/")[-1].split(".")[0] try: save_path = os.path.join(save_dir, name + ".step") _process(path, save_path) except Exception as e: print("load and create failed.") traceback.print_exc() print(name) error_list.append(name) for error in error_list: print(error)