quantum-transformer-analyzer / geometry_engine.py
GlimmaryKarl's picture
Upload geometry_engine.py with huggingface_hub
a2bb29b verified
Raw
History Blame Contribute Delete
4.12 kB
import pandas as pd
import numpy as np
import os
import ezdxf
from pathlib import Path
def process_mesh(input_csv_path: str, dxf_dir_path: str, max_faces=500, precision=2) -> str:
"""
V66 Geometry Engine: Optimized for Low-Disk usage on Hugging Face.
Processes coordinate lines directly from dynamic session paths.
"""
print(f" -> Processing Optimized Mesh from: {dxf_dir_path}")
dxf_dir = Path(dxf_dir_path)
if not dxf_dir.exists():
raise FileNotFoundError(f"DXF directory not found at {dxf_dir}")
all_points = []
dxf_files = sorted(list(dxf_dir.glob("*.dxf")))
# --- STRATEGY 1: FRAME SAMPLING ---
if len(dxf_files) > 60:
print(f" -> High frame count ({len(dxf_files)}). Downsampling for performance.")
dxf_files = dxf_files[::2]
for dxf_file in dxf_files:
try:
# Safely isolate frame index numerical components
frame_id = int(''.join(filter(str.isdigit, dxf_file.stem)) or 0)
doc = ezdxf.readfile(dxf_file)
msp = doc.modelspace()
# --- STRATEGY 2: VERTEX DECIMATION ---
entities = msp.query('LINE')
sampling_rate = 2 if len(entities) > 500 else 1
for i, entity in enumerate(entities):
if i % sampling_rate != 0:
continue
all_points.append({'t': frame_id, 'x': entity.dxf.start.x, 'y': entity.dxf.start.y, 'z': entity.dxf.start.z})
all_points.append({'t': frame_id, 'x': entity.dxf.end.x, 'y': entity.dxf.end.y, 'z': entity.dxf.end.z})
except Exception:
continue
if not all_points:
raise ValueError("No valid point geometry vectors could be parsed from DXF tracking layers.")
df_vertices = pd.DataFrame(all_points)
final_results = []
center_x, center_y = df_vertices['x'].mean(), df_vertices['y'].mean()
for frame_id, group in df_vertices.groupby('t'):
if len(group) < 2: continue
group = group.drop_duplicates(subset=['x', 'y']).copy()
group['dist'] = np.sqrt((group['x'] - center_x)**2 + (group['y'] - center_y)**2)
group = group.sort_values('dist')
# --- STRATEGY 3: FACE LIMITING ---
window_size = 2
rolling = group.rolling(window=window_size)
for i, window in enumerate(rolling):
if len(window) < window_size or i > max_faces:
continue
pts = window[['x', 'y', 'z']].values
cp_x, cp_y = np.mean(pts[:, 0]), np.mean(pts[:, 1])
avg_dist = np.mean(window['dist'])
d_min, d_max = group['dist'].min(), group['dist'].max()
span = (d_max - d_min) if d_max != d_min else 1
norm = (avg_dist - d_min) / span
r, g, b = int(255 * norm), int(255 * (1 - norm)), int(255 * (0.5 + 0.5 * np.sin(norm * np.pi)))
dynamic_z = float(frame_id + 1.0) * (r + g + b)
v1 = pts[1] - pts[0]
v2 = np.array([0, 0, dynamic_z])
normal = np.cross(v1, v2)
norm_val = np.linalg.norm(normal)
normal_unit = normal / norm_val if norm_val > 1e-9 else np.array([0, 0, 1])
# --- STRATEGY 4: STRING FORMATTING & ROUNDING ---
row = (f"{frame_id},"
f"{cp_x:.{precision}f},"
f"{cp_y:.{precision}f},"
f"{dynamic_z:.1f},"
f"{r},{g},{b},"
f"{normal_unit[0]:.2f},{normal_unit[1]:.2f},{normal_unit[2]:.2f},"
f"{np.linalg.norm(v1):.2f},"
f"{np.arccos(np.clip(np.dot([0,0,1], normal_unit), -1.0, 1.0)):.2f}")
final_results.append(row)
# Save output to the exact same temporary folder directory as the input CSV path
output_path = os.path.dirname(input_csv_path) + "/final_12d_features.csv"
with open(output_path, 'w') as f:
f.write("t,x,y,z,R,G,B,N_x,N_y,N_z,d,th\n")
f.write("\n".join(final_results))
return output_path