# encoding: UTF-8
# cut2 — SWD_04_t9_240x1046 양끝 볼트결합부만 제거 (남길 x 111..889 만 keep-box 로 intersect)
#   cut1 실패 원인: box.transformation= 로 박스를 배치 -> 실제 위치 어긋나 교집합 0 -> 부재 전체 소멸.
#   이번엔 8개 꼭짓점을 부모좌표로 직접 변환해 박스를 만든다. intersect 전에 겹침 검사 필수.

HB = 'E:/도진팩토리/3D스캔및티칭시스템/_자동화/inbox/_보류/_cut2_heartbeat.txt'
def hb(msg)
  begin
    File.open(HB, 'a:UTF-8') { |f| f.write("[#{Time.now.strftime('%H:%M:%S')}] #{msg}\n"); f.flush }
  rescue Exception
    nil
  end
end
def r1(v); (v * 25.4).round(1); end

m = Sketchup.active_model
out = []
hb("START")

parent = m.entities.grep(Sketchup::Group).find { |g| g.definition.name == "그룹#2" }
cands = parent ? parent.entities.grep(Sketchup::Group).select { |g| g.name == "SWD_04_t9_240x1046" } : []
if cands.length != 1
  out << "대상 #{cands.length}개 -> 중단"
  hb("ABORT cand=#{cands.length}")
else
  tgt = cands[0]
  lb = tgt.definition.bounds
  loops = 0
  tgt.entities.grep(Sketchup::Face).each { |f| f.loops.each { |lp| loops += 1 unless lp.outer? } }
  out << "대상 로컬 #{r1(lb.width)}x#{r1(lb.height)}x#{r1(lb.depth)} 내부루프=#{loops} solid=#{tgt.manifold?}"
  ok = (r1(lb.width) - 1000.0).abs < 1.0 && loops == 18 && tgt.manifold?
  if !ok
    out << "형상 확인 실패 -> 중단, 무변경"
    hb("ABORT shape")
  else
    begin
      base = File.basename(m.path, '.skp'); dir = File.dirname(m.path)
      bak = File.join(dir, "#{base}.bak_#{Time.now.strftime('%Y%m%d_%H%M%S')}_cut2직전.skp")
      m.save_copy(bak)
      out << "사전 백업 OK -> #{bak}"
      hb("BACKUP OK")
    rescue Exception => e
      out << "백업 실패 #{e.message} -> 중단"; hb("BACKUP FAIL"); ok = false
    end

    if ok
      nm = tgt.name
      lay = (tgt.layer rescue nil)
      mat = (tgt.material rescue nil)
      tr = tgt.transformation
      pents = parent.entities
      tb = tgt.bounds
      res = nil
      begin
        m.start_operation("SWD_04 양끝 볼트결합부 제거", true)
        pt = lambda { |x, y, z| tr * Geom::Point3d.new(x.mm, y.mm, z.mm) }
        x0 = 111.0; x1 = 889.0; y0 = -20.0; y1 = 260.0; z0 = -20.0; z1 = 130.0
        c000 = pt.call(x0, y0, z0); c100 = pt.call(x1, y0, z0); c110 = pt.call(x1, y1, z0); c010 = pt.call(x0, y1, z0)
        c001 = pt.call(x0, y0, z1); c101 = pt.call(x1, y0, z1); c111 = pt.call(x1, y1, z1); c011 = pt.call(x0, y1, z1)
        box = pents.add_group
        be = box.entities
        be.add_face(c000, c100, c110, c010)
        be.add_face(c001, c101, c111, c011)
        be.add_face(c000, c100, c101, c001)
        be.add_face(c100, c110, c111, c101)
        be.add_face(c110, c010, c011, c111)
        be.add_face(c010, c000, c001, c011)
        bb = box.bounds
        ov = Geom::BoundingBox.new; ov.add(tb); # 겹침 판정
        inter_ok = !(bb.max.x < tb.min.x || bb.min.x > tb.max.x ||
                     bb.max.y < tb.min.y || bb.min.y > tb.max.y ||
                     bb.max.z < tb.min.z || bb.min.z > tb.max.z)
        out << "박스 world (#{r1(bb.min.x)},#{r1(bb.min.y)},#{r1(bb.min.z)})..(#{r1(bb.max.x)},#{r1(bb.max.y)},#{r1(bb.max.z)}) solid=#{box.manifold?} 겹침=#{inter_ok}"
        hb("BOX solid=#{box.manifold?} overlap=#{inter_ok}")
        if !box.manifold? || !inter_ok
          box.erase!
          out << "박스 불량 또는 미겹침 -> 절단 취소(무변경)"
          hb("BOX BAD -> skip")
        else
          res = tgt.intersect(box)
          hb("INTERSECT res=#{res.class}")
          if res
            res.name = nm
            res.layer = lay if lay
            res.material = mat if mat
            rb = res.bounds
            out << "결과 world (#{r1(rb.min.x)},#{r1(rb.min.y)},#{r1(rb.min.z)})..(#{r1(rb.max.x)},#{r1(rb.max.y)},#{r1(rb.max.z)}) solid=#{res.manifold?}"
          else
            out << "intersect 결과 nil"
          end
        end
        m.commit_operation
        hb("COMMIT OK")
      rescue Exception => ex
        m.commit_operation rescue nil
        out << "ERR #{ex.class}: #{ex.message}"
        hb("ERR #{ex.message}")
      end
    end
  end
end
puts out.join("\n")
hb("END")
"CUT2"
