File size: 4,428 Bytes
3a8a707
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import os
import numpy as np
import pandas as pd
import ezdxf
from pathlib import Path
from scipy.spatial import KDTree

def fit_and_solve_closed_polynomial(pts: np.ndarray) -> dict:
    """
    Fits 5 points into a 2D quadric polynomial curve: Ax^2 + Bxy + Cy^2 + Dx + Ey + F = 0
    Returns solved algebraic coefficients and roots for the dataset.
    """
    if len(pts) < 5:
        # Pad with zeros if fewer than 5 points exist
        return {"A": 0.0, "B": 0.0, "C": 0.0, "D": 0.0, "E": 0.0, "F": 0.0, "root_x": 0.0, "root_y": 0.0}

    x = pts[:, 0]
    y = pts[:, 1]

    # Form design matrix for implicit conic curve fitting: Ax^2 + Bxy + Cy^2 + Dx + Ey = 1 (F = -1)
    M = np.column_stack([x**2, x * y, y**2, x, y])
    rhs = np.ones(len(pts))

    try:
        # Solve algebraic coefficients via least squares SVD
        coeffs, _, _, _ = np.linalg.lstsq(M, rhs, rcond=None)
        A, B, C, D, E = coeffs
        F = -1.0
    except Exception:
        A, B, C, D, E, F = 0.0, 0.0, 0.0, 0.0, 0.0, 0.0

    # Solve critical manifold center point (root solutions where derivatives = 0)
    # dP/dx = 2Ax + By + D = 0 ; dP/dy = Bx + 2Cy + E = 0
    det = 4 * A * C - B**2
    if abs(det) > 1e-6:
        root_x = (B * E - 2 * C * D) / det
        root_y = (B * D - 2 * A * E) / det
    else:
        root_x, root_y = np.mean(x), np.mean(y)

    return {
        "poly_A": float(A),
        "poly_B": float(B),
        "poly_C": float(C),
        "poly_D": float(D),
        "poly_E": float(E),
        "poly_F": float(F),
        "root_x": float(root_x),
        "root_y": float(root_y)
    }

def process_mesh(input_csv_path: str, dxf_dir_path: str, max_faces=500, precision=2) -> pd.DataFrame:
    """
    Reads DXF files, interpolates closed curves from 5 nearest neighbor points,
    solves quadric polynomials, and returns the solved polynomial dataset.
    """
    print(f"    -> Processing Polynomial Geometry directly from DXF: {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")))

    if len(dxf_files) > 60:
        dxf_files = dxf_files[::2] 

    for dxf_file in dxf_files:
        try:
            frame_id = int(''.join(filter(str.isdigit, dxf_file.stem)) or 0)
            doc = ezdxf.readfile(dxf_file)
            msp = doc.modelspace()
            
            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 layers.")

    df_vertices = pd.DataFrame(all_points)
    solved_dataset_rows = []

    for frame_id, group in df_vertices.groupby('t'):
        if len(group) < 5: 
            continue
        
        pts_2d = group[['x', 'y']].drop_duplicates().values
        if len(pts_2d) < 5:
            continue

        # Construct KD-Tree to locate 5 closest points for interpolated closed curves
        tree = KDTree(pts_2d)
        visited = set()

        for idx, pt in enumerate(pts_2d):
            if idx in visited or len(solved_dataset_rows) >= max_faces:
                continue

            # Query 5 nearest neighbors to form interpolated closed boundary loop
            distances, indices = tree.query(pt, k=min(5, len(pts_2d)))
            cluster_pts = pts_2d[indices]
            
            # Solve quadric polynomial equations for the closed boundary
            poly_sol = fit_and_solve_closed_polynomial(cluster_pts)
            poly_sol['frame_id'] = frame_id
            poly_sol['mean_z'] = float(group['z'].mean())
            
            solved_dataset_rows.append(poly_sol)

    # Compile solved polynomial representations directly into pandas dataset
    dataset_df = pd.DataFrame(solved_dataset_rows)
    print(f"    ✅ Generated {len(dataset_df)} solved polynomial curves for dataset.")
    return dataset_df