# encoding: UTF-8
begin
  puts "###DZW-RESTORE-BEND-20260920"
  m = Sketchup.active_model
  bk = 'E:/도진팩토리/3D스캔및티칭시스템/_자동화/autosave/BACKUP_before_restore.skp'
  m.save_copy(bk)
  puts "BACKUP=#{bk}"
  drop = 20.0
  # [이름, 원형 절곡선(mid,월드X), 원형 런(하단), 원형 앞끝X, 원형 앞끝하단Z, 원형 절곡하단Z, 원형 경사각]
  spec = [
    ['RJ102-0604_LH_20260918', 4424.7, 575.4, 3848.5, 85.4, 20.4, 6.4455],
    ['RJ102-0602_RH_20260918', 4415.1, 580.3, 3833.8, 88.8, 23.8, 6.3909]
  ]
  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
  spec.each do |nm, cr_o, run_o, xt_o, zt_o, zc_o, ang_o|
    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 }
    cr_now = (crv.map { |v| wp[v].x.to_mm }.min + crv.map { |v| wp[v].x.to_mm }.max) / 2.0
    k = (cr_o - x_tip) / (cr_now - x_tip)
    puts "-- #{nm}: 현재 절곡선 #{cr_now.round(1)} -> 복원목표 #{cr_o} (역배율 #{k.round(6)}), 앞끝 #{x_tip.round(1)}"
    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 + drop
      else
        nx = x_tip + (x - x_tip) * k
        nz = z + drop * ((nx - x_tip) / run_o)
      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
    puts "   복원 정점 #{mv.length}/#{verts.length}"
    plan << [nm, g, mv, vc, cr_o, run_o, xt_o, zt_o, zc_o, ang_o]
  end
  if bad || plan.length != 2
    puts "STOP: 복원 중단"
  else
    m.start_operation('절곡판 2개 원형 복구', true)
    plan.each { |a| a[1].entities.transform_by_vectors(a[2], a[3]) }
    m.commit_operation
    allok = true
    plan.each do |nm, g, cr_o, run_o, xt_o, zt_o, zc_o, ang_o|
      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
      crz = cr2.map { |p| p.z.to_mm }.min
      crzh = cr2.map { |p| p.z.to_mm }.max
      xcl = cr2.select { |p| (p.z.to_mm - crz).abs < 0.05 }.map { |p| p.x.to_mm }.min
      tz = pts.select { |p| p.x.to_mm <= xs.min + 0.5 }.map { |p| p.z.to_mm }.min
      tzh = pts.select { |p| p.x.to_mm <= xs.min + 0.5 }.map { |p| p.z.to_mm }.max
      am = Math.atan((tz - crz) / (xcl - xs.min)) * 180.0 / Math::PI
      b = g.bounds
      d1 = (crx - cr_o).abs
      d2 = (tz - zt_o).abs
      d3 = (crz - zc_o).abs
      d4 = (am - ang_o).abs
      allok = false if d1 > 0.3 || d2 > 0.2 || d3 > 0.2 || d4 > 0.01
      puts "== #{nm}"
      puts "   절곡선X #{crx.round(1)} (원형 #{cr_o}, 차 #{d1.round(2)}) / 절곡하단Z #{crz.round(1)} (원형 #{zc_o}, 차 #{d3.round(2)}) / 절곡상단Z #{crzh.round(1)}"
      puts "   앞끝 X #{xs.min.round(1)} (원형 #{xt_o}) Z #{tz.round(1)} (원형 #{zt_o}, 차 #{d2.round(2)}) 상단Z #{tzh.round(1)}"
      puts "   절곡높이 #{(tzh - crzh).round(1)}mm / 경사각 #{am.round(4)}deg (원형 #{ang_o}, 차 #{d4.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}"
    end
    puts "검증: #{allok ? '원형 일치' : '불일치 있음'}"
    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
