HoLa-BRep-test / eval /check_valid.py
YuXingyao's picture
Initial commit
990e2a9
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("read.stdsameparameter.mode", 1)
# Interface_Static.SetIVal("read.surfacecurve.mode", 3)
#
# Interface_Static.SetCVal("write.step.schema", "DIS")
Interface_Static.SetIVal("write.precision.mode", 2)
Interface_Static.SetRVal("write.precision.val", 1e-1)
# Interface_Static.SetIVal("write.surfacecurve.mode", 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()
# Walk through the directory tree starting from the root folder
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:
# Check if the file ends with the specified prefix
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)
# Load cad data
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})
# else:
# print(f"Invalid CAD solid: {step_file}")
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))
# Normalize
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.")