# encoding: UTF-8
begin
  puts "###DZW-DROP20-20260920"
  m = Sketchup.active_model
  bk = 'E:/도진팩토리/3D스캔및티칭시스템/_자동화/autosave/BACKUP_before_drop20.skp'
  m.save_copy(bk)
  puts "BACKUP=#{bk}"

  drop = 20.0
  parts = {}
  others = []
  m.active_entities.each do |e|
    next unless e.is_a?(Sketchup::Group) || e.is_a?(Sketchup::ComponentInstance)
    nm = (e.respond_to?(:name) ? e.name.to_s : '')
    if nm == 'RJ102-0604_LH_20260918' || nm == 'RJ102-0602_RH_20260918'
      parts[nm] = e
    else
      others << [e, nm]
    end
  end
  if parts.empty?
    puts "STOP: 대상 부재 미발견"
  else
    plan = []
    parts.each do |nm, g|
      tr = g.transformation
      verts = []
      g.entities.grep(Sketchup::Edge).each { |ed| ed.vertices.each { |v| verts << v } }
      verts.uniq!
      wp = {}
      verts.each { |v| wp[v] = v.position.transform(tr) }
      ux = verts.map { |v| wp[v].x.to_mm }.uniq.sort
      gi = 0
      gv = -1.0
      (0...(ux.length - 1)).each do |i|
        dd = ux[i + 1] - ux[i]
        if dd > gv
          gv = dd
          gi = i
        end
      end
      x_gap = ux[gi]
      x_tip = ux[0]
      crv = verts.select { |v| wp[v].x.to_mm >= x_gap - 3.0 && wp[v].x.to_mm <= x_gap + 0.01 }
      tipv = verts.select { |v| wp[v].x.to_mm <= x_tip + 0.5 }
      z_cr_lo = crv.map { |v| wp[v].z.to_mm }.min
      z_tip_lo = tipv.map { |v| wp[v].z.to_mm }.min
      x_cr_lo = crv.select { |v| (wp[v].z.to_mm - z_cr_lo).abs < 0.05 }.map { |v| wp[v].x.to_mm }.min
      run = x_cr_lo - x_tip
      a0 = Math.atan((z_tip_lo - z_cr_lo) / run) * 180.0 / Math::PI
      a1 = Math.atan((z_tip_lo - (z_cr_lo - drop)) / run) * 180.0 / Math::PI
      rear_z = verts.select { |v| wp[v].x.to_mm > x_gap + 0.01 }.map { |v| wp[v].z.to_mm }
      puts "-- #{nm}: tip=#{x_tip.round(1)}/Z#{z_tip_lo.round(1)}  절곡선=#{x_cr_lo.round(1)}/Z#{z_cr_lo.round(1)}  런=#{run.round(1)}"
      puts "   뒤평판 Z=[#{rear_z.min.round(1)},#{rear_z.max.round(1)}] -> [#{(rear_z.min - drop).round(1)},#{(rear_z.max - drop).round(1)}]"
      puts "   경사각(계산) #{a0.round(4)} -> #{a1.round(4)}deg"
      mv = []
      vc = []
      verts.each do |v|
        x = wp[v].x.to_mm
        dz = if x > x_gap + 0.01
               -drop
             else
               -drop * ((x - x_tip) / run)
             end
        next if dz.abs < 1.0e-6
        w2 = Geom::Point3d.new(wp[v].x, wp[v].y, wp[v].z + dz.mm)
        mv << v
        vc << (w2.transform(tr.inverse) - v.position)
      end
      puts "   변형 정점 #{mv.length}/#{verts.length}, 면수(전)=#{g.entities.grep(Sketchup::Face).length}"
      plan << [nm, g, mv, vc, x_tip, z_tip_lo, x_cr_lo, z_cr_lo, run, a0, a1]
    end
    m.start_operation('뒤 평판 20mm 하강', true)
    plan.each { |a| a[1].entities.transform_by_vectors(a[2], a[3]) }
    m.commit_operation
    plan.each do |nm, g, mv, vc, x_tip, z_tip_lo, x_cr_lo, z_cr_lo, run, a0, a1|
      pts = []
      g.entities.grep(Sketchup::Edge).each { |ed| ed.vertices.each { |v| pts << v.position.transform(g.transformation) } }
      xmin = pts.map { |p| p.x.to_mm }.min
      xmax = pts.map { |p| p.x.to_mm }.max
      ntip = pts.select { |p| p.x.to_mm <= xmin + 0.5 }.map { |p| p.z.to_mm }.min
      ncr = pts.select { |p| (p.x.to_mm - x_cr_lo).abs < 0.6 }.map { |p| p.z.to_mm }.min
      nrear = pts.select { |p| p.x.to_mm >= xmax - 0.5 }.map { |p| p.z.to_mm }
      am = Math.atan((ntip - ncr) / (x_cr_lo - xmin)) * 180.0 / Math::PI
      b = g.bounds
      puts "== #{nm} 면수(후)=#{g.entities.grep(Sketchup::Face).length}"
      puts "   앞끝 Z #{z_tip_lo.round(1)} -> #{ntip.round(1)} (고정확인), 절곡선 Z #{z_cr_lo.round(1)} -> #{ncr.round(1)}"
      puts "   뒤끝 Z=[#{nrear.min.round(1)},#{nrear.max.round(1)}]"
      puts "   경사각(실측) #{a0.round(4)} -> #{am.round(4)}deg (#{(am - a0).round(4)} 변화)"
      puts "   bbox min=#{b.min.to_a.map { |v| v.to_mm.round(1) }.inspect} max=#{b.max.to_a.map { |v| v.to_mm.round(1) }.inspect}"
      ov = []
      others.each do |e, onm|
        ob = e.bounds
        ox = [ob.max.x.to_mm, b.max.x.to_mm].min - [ob.min.x.to_mm, b.min.x.to_mm].max
        oy = [ob.max.y.to_mm, b.max.y.to_mm].min - [ob.min.y.to_mm, b.min.y.to_mm].max
        oz = [ob.max.z.to_mm, b.max.z.to_mm].min - [ob.min.z.to_mm, b.min.z.to_mm].max
        next unless ox > 0.5 && oy > 0.5 && oz > 0.5
        ov << "     BBOX겹침 '#{onm}' #{ox.round(1)}x#{oy.round(1)}x#{oz.round(1)}"
      end
      puts "   bbox 겹침 #{ov.length}건"
      ov.first(10).each { |s| puts s }
    end
    ok = m.save
    puts "SAVE=#{ok.inspect} modified?=#{m.modified?.inspect}"
    puts "DONE"
  end
rescue Exception => e
  puts "EXC #{e.class}: #{e.message}"
  puts e.backtrace.first(5).join(" | ")
end
nil
