#!/usr/bin/env python
import sys
import os
sys.path.insert(0, 'c:/private/MCP-for-MS-Copilot')
from src.tools import _get_autocad_application, _get_insertion_point, _get_bounding_box, _normalize_text, _cluster_by_y
layer_name = os.getenv("LAYER_SHOP_FIELD", "MATLIST")
categories_str = os.getenv("MATERIAL_CATEGORIES", "SHOP MATERIAL,FIELD MATERIAL")
categories = [cat.strip() for cat in categories_str.split(",") if cat.strip()]
row_tolerance = float(os.getenv("ROW_TOLERANCE", "3.0"))
acad, err = _get_autocad_application()
if err:
print(f"에러: {err}")
sys.exit(1)
doc = acad.ActiveDocument
text_items = []
for obj in doc.ModelSpace:
if obj.EntityName not in ["AcDbText", "AcDbMText"]:
continue
if obj.Layer != layer_name:
continue
point = _get_insertion_point(obj)
if not point:
continue
raw_text = getattr(obj, "TextString", "")
norm_text = _normalize_text(str(raw_text))
if not norm_text:
continue
bbox = _get_bounding_box(obj)
if bbox is None:
continue
text_items.append({
"text": str(raw_text),
"norm": norm_text,
"x": point[0],
"y": point[1],
"bbox": bbox,
})
category_map = {c.upper(): c for c in categories}
category_items = [item for item in text_items if item["norm"].upper() in category_map]
print("=" * 80)
print("카테고리 헤더 찾음:")
print("=" * 80)
for cat_item in category_items:
print(f" {cat_item['norm']} @ Y={cat_item['y']:.2f}")
sorted_category_items = sorted(category_items, key=lambda x: x["y"], reverse=True)
for idx, cat_item in enumerate(sorted_category_items):
category_name = category_map[cat_item["norm"].upper()]
if idx + 1 < len(sorted_category_items):
next_cat_y = sorted_category_items[idx + 1]["y"]
else:
next_cat_y = float("-inf")
items_below = [
item for item in text_items
if item["y"] < cat_item["y"] - row_tolerance and item["y"] > next_cat_y
]
if not items_below:
print(f"\n{category_name}: 아래에 텍스트 없음")
continue
rows = _cluster_by_y(items_below, row_tolerance)
sorted_rows = sorted(rows, key=lambda x: x["y"], reverse=True)
first_below_item = max(items_below, key=lambda x: x["y"])
header_start_y = first_below_item["y"]
header_merge_tolerance_wide = row_tolerance * 3.0
header_rows = [row for row in sorted_rows if header_start_y - header_merge_tolerance_wide <= row["y"] <= header_start_y]
header_base_y = min(row["y"] for row in header_rows)
header_cutoff_y = header_base_y - (row_tolerance * 0.5)
data_rows = [row for row in rows if row["y"] < header_cutoff_y]
# first column items 기준 row markers 계산
first_col_items = []
for row in data_rows:
for item in row["items"]:
bbox = item.get("bbox")
if bbox is None:
continue
min_x, min_y, max_x, max_y = bbox
if max_y >= header_cutoff_y:
continue
first_col_items.append(item)
first_col_items = sorted(first_col_items, key=lambda x: x["bbox"][3], reverse=True)
row_markers = []
for item in first_col_items:
bbox = item.get("bbox")
if bbox is None:
continue
row_top_y = bbox[3]
if not row_markers or abs(row_top_y - row_markers[-1]) > row_tolerance:
row_markers.append(row_top_y)
if not row_markers:
print(f"\n{category_name}: data row 없음")
continue
row_boundaries = [
(row_markers[i] + row_markers[i + 1]) / 2
for i in range(len(row_markers) - 1)
]
print(f"\n{'=' * 80}")
print(f"{category_name} - Row Y 영역")
print(f"{'=' * 80}")
for i, upper in enumerate(row_markers):
lower = row_boundaries[i] if i < len(row_boundaries) else float("-inf")
print(f"Row {i+1}: {upper:.2f} ~ {lower:.2f}")