# encoding: UTF-8
# mkside — CEO가 만든 측면 막음 면(두께 0)을 9T 판으로 세우고, 반대편에 대칭 복제.
HB = 'E:/도진팩토리/3D스캔및티칭시스템/_자동화/inbox/_보류/_side_heartbeat.txt'
def hb(s)
  begin
    File.open(HB, 'a:UTF-8') { |f| f.write("[#{Time.now.strftime('%H:%M:%S')}] #{s}\n"); f.flush }
  rescue Exception
    nil
  end
end
MM = 25.4
def r2(v); (v * 25.4).round(2); end
m = Sketchup.active_model
out = []
hb("START")
# 1) 대상 면: 최상위 loose Face 중 최신
face = m.entities.grep(Sketchup::Face).sort_by { |f| -f.entityID }.first
if face.nil?
  out << "최상위 loose 면 없음 -> 중단"
  hb("ABORT noface")
else
  pts = face.vertices.map { |v| v.position }
  b = face.bounds
  n = face.normal
  out << "대상 면 eid=#{face.entityID} 정점 #{pts.length} 면적 #{(face.area * 645.16).round(0)}mm2 법선 (#{n.x.round(3)},#{n.y.round(3)},#{n.z.round(3)})"
  out << "  bbox (#{r2(b.min.x)},#{r2(b.min.y)},#{r2(b.min.z)})..(#{r2(b.max.x)},#{r2(b.max.y)},#{r2(b.max.z)}) 현재 두께 = 0mm(면)"
  ymm = (b.min.y + b.max.y) / 2.0 * 25.4
  # 2) 간섭 검사: +Y / -Y 9mm 구간에 다른 개체가 있는지
  others = m.entities.to_a.select { |e| (e.is_a?(Sketchup::Group) || e.is_a?(Sketchup::ComponentInstance)) }
  def hits(others, xlo, xhi, ylo, yhi, zlo, zhi)
    others.select do |e|
      bb = e.bounds
      !(bb.max.x * 25.4 < xlo || bb.min.x * 25.4 > xhi ||
        bb.max.y * 25.4 < ylo || bb.min.y * 25.4 > yhi ||
        bb.max.z * 25.4 < zlo || bb.min.z * 25.4 > zhi)
    end.map { |e| e.name.to_s.empty? ? e.definition.name : e.name }
  end
  xlo = b.min.x * 25.4; xhi = b.max.x * 25.4; zlo = b.min.z * 25.4; zhi = b.max.z * 25.4
  inw = hits(others, xlo, xhi, ymm + 0.5, ymm + 9.0, zlo, zhi)
  outw = hits(others, xlo, xhi, ymm - 9.0, ymm - 0.5, zlo, zhi)
  out << "  간섭검사 안쪽(+Y 9mm): #{inw.inspect}"
  out << "  간섭검사 바깥(-Y 9mm): #{outw.inspect}"
  dir = outw.length <= inw.length ? -1.0 : 1.0
  out << "  선택 방향: #{dir < 0 ? '바깥(-Y)' : '안쪽(+Y)'} (간섭 적은 쪽)"
  # 3) 대칭축: 조립체 y 중앙 (SWD_04 기준)
  g2 = m.entities.grep(Sketchup::Group).find { |g| g.definition.name == "그룹#2" }
  s04 = g2.entities.grep(Sketchup::Group).find { |g| g.name == "SWD_04_t9_240x1046" }
  sb = Geom::BoundingBox.new
  [s04.bounds.min, s04.bounds.max].each { |p| sb.add(p.transform(g2.transformation)) }
  ymid = (sb.min.y + sb.max.y) / 2.0 * 25.4
  out << "  대칭축 y=#{ymid.round(2)} (SWD_04 y #{(sb.min.y*25.4).round(1)}..#{(sb.max.y*25.4).round(1)}), 대상판 y=#{ymm.round(2)}, 거울상 y=#{(2 * ymid - ymm).round(2)}"
  begin
    base = File.basename(m.path, '.skp'); dir2 = File.dirname(m.path)
    bak = File.join(dir2, "#{base}.bak_#{Time.now.strftime('%Y%m%d_%H%M%S')}_side9T직전.skp")
    m.save_copy(bak)
    hb("BACKUP OK")
    m.start_operation("사이드막음판 9T 양쪽", true)
    made = []
    [[ymm, "사이드막음판_9T_A_20260919", 1.0], [2 * ymid - ymm, "사이드막음판_9T_B_20260919", -1.0]].each do |ytar, nm, mir|
      g = m.entities.add_group
      poly = pts.map do |p|
        yy = (mir > 0) ? p.y : (2 * ymid / 25.4 - p.y)
        Geom::Point3d.new(p.x, yy, p.z)
      end
      f = g.entities.add_face(poly)
      d = 9.0 / MM * dir * (mir > 0 ? 1.0 : -1.0)
      # 면 법선이 ±Y 이므로 pushpull 부호 정리
      f.pushpull(f.normal.y > 0 ? d : -d)
      g.name = nm
      hb("#{nm} solid=#{g.manifold?}")
      bb = g.bounds
      out << "#{nm}: solid=#{g.manifold?} bbox (#{r2(bb.min.x)},#{r2(bb.min.y)},#{r2(bb.min.z)})..(#{r2(bb.max.x)},#{r2(bb.max.y)},#{r2(bb.max.z)}) 두께 #{((bb.max.y - bb.min.y) * 25.4).round(2)}mm"
      made << g
    end
    face.erase!
    m.commit_operation
    hb("COMMIT")
    # 대칭 검증
    a, bg = made
    ab = a.bounds; bb2 = bg.bounds
    out << "대칭 검증: A y #{r2(ab.min.y)}..#{r2(ab.max.y)} / B y #{r2(bb2.min.y)}..#{r2(bb2.max.y)}"
    out << "  거울 오차 = #{(( (ab.min.y + bb2.max.y) / 2.0 * 25.4) - ymid).abs.round(3)}mm, x범위차 #{((ab.max.x - ab.min.x) - (bb2.max.x - bb2.min.x)).abs * 25.4}mm, z범위차 #{(((ab.max.z - ab.min.z) - (bb2.max.z - bb2.min.z)) * 25.4).abs.round(3)}mm"
  rescue Exception => e
    m.commit_operation rescue nil
    out << "ERR #{e.class}: #{e.message}"
    hb("ERR #{e.message}")
  end
end
puts out.join("\n")
hb("END")
"MKSIDE"
