| import random
|
| import shutil
|
| import sys
|
|
|
| from OCC.Core.BRepBuilderAPI import BRepBuilderAPI_MakeSolid
|
| from OCC.Core.BRepCheck import BRepCheck_Analyzer
|
| from OCC.Core.IGESControl import IGESControl_Reader
|
| from OCC.Core.Interface import Interface_Static
|
| from OCC.Core.STEPControl import STEPControl_Reader, STEPControl_Writer, STEPControl_AsIs
|
| from OCC.Core.StepData import StepData_StepModel
|
| from OCC.Core.TopAbs import TopAbs_SOLID, TopAbs_COMPOUND, TopAbs_SHELL, TopAbs_FACE, TopAbs_EDGE
|
| from OCC.Extend.DataExchange import read_step_file
|
| from OCC.Core.ShapeFix import ShapeFix_ShapeTolerance
|
| import os
|
| import argparse
|
| import glob
|
| from tqdm import tqdm
|
| from matplotlib import pyplot as plt
|
| import numpy as np
|
| from diffusion.utils import get_primitives
|
|
|
| os.environ["KMP_DUPLICATE_LIB_OK"] = "TRUE"
|
|
|
| Interface_Static.SetIVal("read.precision.mode", 1)
|
| Interface_Static.SetRVal("read.precision.val", 1e-1)
|
|
|
|
|
|
|
|
|
| Interface_Static.SetIVal("write.precision.mode", 2)
|
| Interface_Static.SetRVal("write.precision.val", 1e-1)
|
|
|
|
|
|
|
|
|
|
|
| def check_step_valid_soild(step_file, precision=1e-1, return_shape=False):
|
| try:
|
| shape = read_step_file(str(step_file), as_compound=False, verbosity=False)
|
| except:
|
| if return_shape:
|
| return False, None
|
| else:
|
| return False
|
| if shape.ShapeType() != TopAbs_SOLID:
|
| if return_shape:
|
| return False, shape
|
| else:
|
| return False
|
| shape_tol_setter = ShapeFix_ShapeTolerance()
|
| shape_tol_setter.SetTolerance(shape, precision)
|
| analyzer = BRepCheck_Analyzer(shape)
|
| is_valid = analyzer.IsValid()
|
| if return_shape:
|
| return is_valid, shape
|
| return is_valid
|
|
|
|
|
| def load_data_with_prefix(root_folder, prefix, folder_list_txt=None):
|
| data_files = []
|
| folder_list = []
|
| if folder_list_txt is not None:
|
| with open(folder_list_txt, "r") as f:
|
| folder_list = f.read().splitlines()
|
|
|
| for root, dirs, files in os.walk(root_folder):
|
| if folder_list_txt is not None and os.path.basename(root) not in folder_list:
|
| continue
|
| is_found = False
|
| for filename in files:
|
|
|
| if filename.endswith(prefix):
|
| file_path = os.path.join(root, filename)
|
| is_found = True
|
| data_files.append(file_path)
|
| if not is_found:
|
| print(f"No {prefix} file found in {root}")
|
|
|
| return data_files
|
|
|
|
|
| if __name__ == "__main__":
|
| parser = argparse.ArgumentParser()
|
| parser.add_argument("--data_root", type=str, required=True)
|
| parser.add_argument("--prefix", type=str, required=False, default="")
|
| parser.add_argument("--only_success", action="store_true", default=False)
|
| args = parser.parse_args()
|
| data_root = args.data_root
|
| only_success = args.only_success
|
| folders = [f for f in os.listdir(data_root) if os.path.isdir(os.path.join(data_root, f))]
|
|
|
| if args.prefix:
|
| step_file_list = load_data_with_prefix(os.path.join(data_root, args.prefix), ".step")
|
| assert len(step_file_list) > 0
|
| print(f"Checking CAD solids in {args.prefix}...")
|
| isvalid = check_step_valid_soild(step_file_list[0], is_set_gloabl=True)
|
| print("Valid" if isvalid else "Invalid")
|
| exit(0)
|
|
|
| step_file_list = load_data_with_prefix(data_root, ".step")
|
|
|
| print(f"Total sample features: {len(folders)}")
|
| print(f"Total CAD solids: {len(step_file_list)}")
|
|
|
| print("Start checking CAD solids...")
|
|
|
| exception_folders = []
|
| exception_out_root = data_root + "_exception"
|
| if os.path.exists(exception_out_root):
|
| shutil.rmtree(exception_out_root)
|
| os.makedirs(exception_out_root, exist_ok=False)
|
|
|
|
|
| valid_count = 0
|
| pbar = tqdm(step_file_list)
|
| num_faces = []
|
| num_edges = []
|
| for step_file in pbar:
|
| is_valid, shape = check_step_valid_soild(step_file, return_shape=True)
|
| if os.path.exists(os.path.join(os.path.dirname(step_file), "success.txt")) and not is_valid:
|
| folder_name = os.path.basename(os.path.dirname(step_file))
|
| exception_folders.append(folder_name)
|
| shutil.copytree(os.path.dirname(step_file), os.path.join(exception_out_root, folder_name))
|
|
|
| if is_valid:
|
| if only_success and not os.path.exists(os.path.join(os.path.dirname(step_file), "success.txt")):
|
| continue
|
| valid_count += 1
|
| num_faces.append(len(get_primitives(shape, TopAbs_FACE)))
|
| num_edges.append(len(get_primitives(shape, TopAbs_EDGE)) // 2)
|
| pbar.set_postfix({"valid_count": valid_count})
|
|
|
|
|
|
|
| fig, ax = plt.subplots(1, 2, layout="constrained")
|
| ax[0].set_title("Num. faces")
|
| ax[1].set_title("Num. edges")
|
| hist_f, bin_f = np.histogram(num_faces, bins=5, range=(0, 30))
|
| hist_e, bin_e = np.histogram(num_edges, bins=5, range=(0, 50))
|
|
|
| hist_f = hist_f / np.sum(hist_f)
|
| hist_e = hist_e / np.sum(hist_e)
|
| ax[0].plot(bin_f[:-1], hist_f, "-")
|
| ax[1].plot(bin_e[:-1], hist_e, "-")
|
| ax[0].set_aspect(1. / ax[0].get_data_ratio())
|
| ax[1].set_aspect(1. / ax[1].get_data_ratio())
|
| plt.savefig(data_root + "_num_faces_edges.png", dpi=600)
|
|
|
| print(f"Number of valid CAD solids: {valid_count}")
|
| print(f"Valid rate: {valid_count / len(folders) * 100:.2f}%")
|
|
|
| if len(exception_folders) > 0:
|
| with open(os.path.join(exception_out_root, "exception_folders.txt"), "w") as f:
|
| for folder in exception_folders:
|
| f.write(folder + "\n")
|
| print(f"Exception folders are saved to {exception_out_root}")
|
| if len(exception_folders) == 0:
|
| shutil.rmtree(exception_out_root)
|
| print("No exception folders found.")
|
|
|