# encoding: UTF-8
# side2 — 측면 막음판 9T 재작성: 실측 개구부(위 주황 하면 수평 / 아래 흰판 경사 6.445도 /
#         좌우 6T 격판 바깥면)에 맞춘 사다리꼴, 좌우 대칭 2장.
HB = 'E:/도진팩토리/3D스캔및티칭시스템/_자동화/inbox/_보류/_side2_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")
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" }
p30 = m.entities.grep(Sketchup::Group).find { |g| g.name == "SWD_02_jog30_6T_20260919" }
p20 = m.entities.grep(Sketchup::Group).find { |g| g.name == "SWD_03_jog20_6T_20260919" }
old = m.entities.grep(Sketchup::Group).select { |g| g.name.to_s.start_with?("사이드막음판") }
if s04.nil? || p30.nil? || p20.nil?
  out << "기준 부재 없음 -> 중단"
  hb("ABORT")
else
  sb = Geom::BoundingBox.new
  [s04.bounds.min, s04.bounds.max].each { |p| sb.add(p.transform(g2.transformation)) }
  ya = sb.min.y * 25.4          # 10879.34
  yb = sb.max.y * 25.4          # 11872.77
  x1 = p20.bounds.min.x * 25.4  # 흰판 높은 쪽 (좌)
  x2 = p30.bounds.max.x * 25.4  # 낮은 쪽 (우)
  ztop = 139.16                 # 주황판 하면(수평) 실측
  # 흰판 상면 경사선: (8800,131.63) - (9260,79.66) 실측 2점
  slope = (79.66 - 131.63) / (9260.0 - 8800.0)
  zb = lambda { |x| 131.63 + slope * (x - 8800.0) }
  h1 = ztop - zb.call(x1)
  h2 = ztop - zb.call(x2)
  out << "개구부 실측: x #{x1.round(2)}..#{x2.round(2)} (폭 #{(x2 - x1).round(2)}mm), 상단 z#{ztop} 수평, 하단 경사 #{(Math.atan(-slope) * 180 / Math::PI).round(4)}도"
  out << "  좌측 높이 #{h1.round(2)}mm / 우측 높이 #{h2.round(2)}mm, 최소 코너각 #{(90 - Math.atan(-slope) * 180 / Math::PI).round(2)}도(예각 없음 -> 모따기 불필요, 대신 하단 양끝 용접 릴리프 10x10 적용)"
  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')}_side2직전.skp")
    m.save_copy(bak)
    hb("BACKUP OK")
    m.start_operation("사이드막음판 9T 외곽 맞춤 2장", true)
    old.each { |g| g.erase! }
    made = []
    [[ya, -1.0, "사이드막음판_9T_A_20260919"], [yb, 1.0, "사이드막음판_9T_B_20260919"]].each do |yy, sgn, nm|
      rel = 10.0   # 용접 릴리프 10mm
      poly = []
      poly << Geom::Point3d.new(x1 / MM, yy / MM, ztop / MM)
      poly << Geom::Point3d.new(x2 / MM, yy / MM, ztop / MM)
      poly << Geom::Point3d.new(x2 / MM, yy / MM, zb.call(x2) / MM)
      poly << Geom::Point3d.new((x2 - rel) / MM, yy / MM, zb.call(x2 - rel) / MM)
      poly << Geom::Point3d.new((x1 + rel) / MM, yy / MM, zb.call(x1 + rel) / MM)
      poly << Geom::Point3d.new(x1 / MM, yy / MM, zb.call(x1) / MM)
      g = m.entities.add_group
      f = g.entities.add_face(poly)
      d = 9.0 / MM
      f.pushpull(f.normal.y * sgn > 0 ? d : -d)
      g.name = nm
      hb("#{nm} solid=#{g.manifold?}")
      made << g
    end
    m.commit_operation
    hb("COMMIT")
    made.each do |g|
      b = g.bounds
      out << "#{g.name}: solid=#{g.manifold?} 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)}) 두께 #{((b.max.y - b.min.y) * 25.4).round(2)}mm"
    end
    a = made[0].bounds; bb = made[1].bounds
    out << "대칭 검증: 폭차 #{(((a.max.x - a.min.x) - (bb.max.x - bb.min.x)) * 25.4).abs.round(4)}mm, 높이차 #{(((a.max.z - a.min.z) - (bb.max.z - bb.min.z)) * 25.4).abs.round(4)}mm, 두께 각각 #{((a.max.y - a.min.y)*25.4).round(2)}/#{((bb.max.y - bb.min.y)*25.4).round(2)}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")
"SIDE2"
