# encoding: UTF-8
begin
  puts "###DZW-APPLY-H80-X4539-20260920"
  m = Sketchup.active_model
  bk = 'E:/도진팩토리/3D스캔및티칭시스템/_자동화/autosave/BACKUP_before_applyH80.skp'
  m.save_copy(bk)
  puts "BACKUP=#{bk}"
  xb = 4539.1
  hgt = 80.0
  names = ['RJ102-0604_LH_20260918', 'RJ102-0602_RH_20260918']
  found = {}
  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 : '')
    found[nm] = e unless nm.empty?
  end
  plan = []
  bad = false
  names.each do |nm|
    g = found[nm]
    if g.nil?
      puts "STOP: '#{nm}' 미발견"
      bad = true
      next
    end
    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 - 4.0 && wp[v].x.to_mm <= x_gap + 0.01 }
    tipv = verts.select { |v| wp[v].x.to_mm <= x_tip + 0.5 }
    cr_x = (crv.map { |v| wp[v].x.to_mm }.min + crv.map { |v| wp[v].x.to_mm }.max) / 2.0
    cr_hi = crv.map { |v| wp[v].z.to_mm }.max
    cr_lo = crv.map { |v| wp[v].z.to_mm }.min
    tip_hi = tipv.map { |v| wp[v].z.to_mm }.max
    tip_lo = tipv.map { |v| wp[v].z.to_mm }.min
    h_now = tip_hi - cr_hi
    rise = h_now - hgt                # 뒤 평판/절곡선을 올릴 양 (126-80=46)
    s = (xb - x_tip) / (cr_x - x_tip) # 앞끝 핀 X 배율
    run_ref = cr_x - x_tip
    x_cr_lo_new = x_tip + (crv.select { |v| (wp[v].z.to_mm - cr_lo).abs < 0.05 }.map { |v| wp[v].x.to_mm }.min - x_tip) * s
    ang_new = Math.atan((tip_lo - (cr_lo + rise)) / (x_cr_lo_new - x_tip)) * 180.0 / Math::PI
    puts "-- #{nm} [월드]"
    puts "   검산: 절곡높이 #{h_now.round(1)} -> #{(h_now - rise).round(1)} (올림 #{rise.round(1)}mm), 절곡선X #{cr_x.round(1)} -> #{(x_tip + (cr_x - x_tip) * s).round(1)} (목표 #{xb}), 배율 #{s.round(5)}"
    puts "   검산: 앞끝 X#{x_tip.round(1)} Z#{tip_lo.round(1)}(하)/#{tip_hi.round(1)}(상) 고정, 예상 경사각 #{ang_new.round(4)}deg"
    if ((h_now - rise) - hgt).abs > 0.01 || ((x_tip + (cr_x - x_tip) * s) - xb).abs > 0.01
      puts "   STOP: 검산 불일치"
      bad = true
      next
    end
    mv = []
    vc = []
    verts.each do |v|
      x = wp[v].x.to_mm
      z = wp[v].z.to_mm
      if x > x_gap + 0.01
        nx = x
        nz = z + rise
      else
        r = (x - x_tip) / run_ref
        nx = x_tip + (x - x_tip) * s
        nz = z + rise * r
      end
      next if (nx - x).abs < 1.0e-9 && (nz - z).abs < 1.0e-9
      w2 = Geom::Point3d.new(nx.mm, wp[v].y, nz.mm)
      mv << v
      vc << (w2.transform(tr.inverse) - v.position)
    end
    plan << [nm, g, mv, vc, h_now, cr_x, s]
    puts "   변형 정점 #{mv.length}/#{verts.length}, 단차 X방향 #{((s - 1) * 100).round(1)}% 신장 예상"
  end
  if bad || plan.length != 2
    puts "STOP: 적용 취소(변경 없음)"
  else
    m.start_operation('절곡높이 80 + 절곡선 간살시작점', true)
    plan.each { |a| a[1].entities.transform_by_vectors(a[2], a[3]) }
    m.commit_operation
    plan.each do |a|
      nm = a[0]
      g = a[1]
      h0 = a[4]
      cr0 = a[5]
      sc = a[6]
      pts = []
      g.entities.grep(Sketchup::Edge).each { |ed| ed.vertices.each { |v| pts << v.position.transform(g.transformation) } }
      xs = pts.map { |p| p.x.to_mm }
      ux2 = xs.uniq.sort
      gi2 = 0
      gv2 = -1.0
      (0...(ux2.length - 1)).each do |i|
        dd = ux2[i + 1] - ux2[i]
        if dd > gv2
          gv2 = dd
          gi2 = i
        end
      end
      xg2 = ux2[gi2]
      cr2 = pts.select { |p| p.x.to_mm >= xg2 - 4.0 && p.x.to_mm <= xg2 + 0.01 }
      crx = (cr2.map { |p| p.x.to_mm }.min + cr2.map { |p| p.x.to_mm }.max) / 2.0
      crhi = cr2.map { |p| p.z.to_mm }.max
      crlo = cr2.map { |p| p.z.to_mm }.min
      xcl = cr2.select { |p| (p.z.to_mm - crlo).abs < 0.05 }.map { |p| p.x.to_mm }.min
      tp = pts.select { |p| p.x.to_mm <= xs.min + 0.5 }
      thi = tp.map { |p| p.z.to_mm }.max
      tlo = tp.map { |p| p.z.to_mm }.min
      am = Math.atan((tlo - crlo) / (xcl - xs.min)) * 180.0 / Math::PI
      b = g.bounds
      puts "== #{nm} 면수=#{g.entities.grep(Sketchup::Face).length} hidden=#{g.hidden?}"
      puts "   절곡높이(월드) #{h0.round(1)} -> #{(thi - crhi).round(2)}mm  [목표 80]"
      puts "   절곡선 월드X #{cr0.round(1)} -> #{crx.round(2)}  [목표 #{xb}]"
      puts "   앞끝 X #{xs.min.round(1)} Z #{tlo.round(1)}(하)/#{thi.round(1)}(상) 고정확인"
      puts "   경사각(실측) #{am.round(4)}deg, 런 #{(xcl - xs.min).round(1)}, 단차 X #{((sc - 1) * 100).round(1)}% 신장"
      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}"
    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
