# -*- coding: utf-8 -*-
r"""T600 프레임 전용 후처리: 표 칸(도면 비품) 오인식 부재를 산출물에서 격리한다.

왜 이 파일이 있어야 하나
------------------------
pass6 는 T600 프레임에서 부재 135개를 만드는데 그중 18개가 부재가 아니다.
도면 비품(표 칸)을 부재로 잡은 것이고, 이건 게이트로 막지 못한다는 걸 실측으로 확인했다
(product.py 의 t600_frame 주석 참조 — dim_gate 는 정상부재 23개를 같이 죽이고,
글자거리는 표 칸 34~51mm 와 정상 0~185mm 가 겹쳐 선을 그을 수 없다).

그래서 '만든 뒤에 빼는' 방식으로 처리하는데, 이걸 사람 손으로 하면 다음 실행에서
조용히 135개로 돌아간다(manifest 도 135건이 되고 SKP 에 표 칸 18개가 섞인다).
파이프라인을 돌린 사람이 이 사실을 기억하지 못해도 같은 결과가 나오도록 파일로 남긴다.

무엇을 근거로 고르나 (크기 임계값이 아니다)
-------------------------------------------
표 칸은 정확히 두 가지 크기로만 나온다. 132.63 x 34.64 와 88.42 x 23.10 이고
두 크기의 비는 정확히 1.5 — 같은 도형을 축척만 바꿔 그린 것이다.
이 도형은 도면 전체에 174개(139 + 35)가 똑같이 반복되며 주변 60mm 안에 글자가 0개다.
'대충 이 정도 크기' 가 아니라 '도면에 실재하는 특정 도형 두 개' 를 지목하는 것이라
±0.05mm 로 정확히 일치할 때만 격리한다(정상 부재가 우연히 걸릴 여지를 두지 않는다).

사용
----
    python pass6_multi.py --product t600_frame --bom
    python quarantine_t600_frame.py          <- pass6 직후 반드시 실행
    python add_manifest.py --product t600_frame

지우지 않는다 — scratchpad\t600\_격리_표칸18건\ 으로 옮기기만 한다(데이터 손실 금지).
"""
import glob
import os
import shutil
import sys

import trimesh

sys.argv = [sys.argv[0], '--product', 't600_frame']
import product

if product.NAME != 't600_frame':
    raise SystemExit('이 스크립트는 t600_frame 전용이다 (현재: %s)' % product.NAME)

FAB = product.FAB
QUAR = product.SCR + r'\_격리_표칸18건'

# (긴변, 짧은변) — 도면에 실재하는 표 칸 도형 두 가지. 위 설명 참조.
TABLE_CELLS = [(132.63, 34.64), (88.42, 23.10)]
TOL = 0.05


def is_table_cell(obj_path):
    """이 OBJ 의 평면 크기가 표 칸 도형과 정확히 일치하는가.

    두께는 도번마다 다르므로(6T~45T) 크기 비교에서 뺀다. 두께가 짧은 변보다 두꺼운
    부재가 있어서(예: 88.42 x 23.10 x 45.0) extents 를 그냥 정렬하면 두께가 끼어들어
    놓친다. 그래서 '두께를 제외한 나머지 두 변' 을 평면 크기로 본다.
    """
    e = sorted(trimesh.load(obj_path, force='mesh').extents, reverse=True)
    # 압출 두께는 pass6 가 z 로 넣는다. 평면 두 변은 나머지 두 값이다.
    for cand in ((e[0], e[1]), (e[0], e[2]), (e[1], e[2])):
        for W, H in TABLE_CELLS:
            if abs(cand[0] - W) < TOL and abs(cand[1] - H) < TOL:
                return True
    return False


def main():
    if not os.path.isdir(QUAR):
        os.makedirs(QUAR)
    moved = []
    for f in sorted(glob.glob(os.path.join(FAB, '*.obj'))):
        if is_table_cell(f):
            shutil.move(f, os.path.join(QUAR, os.path.basename(f)))
            moved.append(os.path.basename(f))
    left = len(glob.glob(os.path.join(FAB, '*.obj')))
    print('표 칸 격리 %d건 -> 남은 부재 %d건' % (len(moved), left))
    for m in moved:
        print('   ', m)
    if not moved:
        print('  (이미 격리된 상태이거나 pass6 를 아직 안 돌렸다)')
    print('격리 위치:', QUAR)


if __name__ == '__main__':
    main()
