# encoding: UTF-8
begin
  puts "###DZW-STEP2-SWD04-20260920"
  m = Sketchup.active_model
  bk = 'E:/도진팩토리/3D스캔및티칭시스템/_자동화/autosave/BACKUP_before_step2.skp'
  m.save_copy(bk)
  puts "BACKUP=#{bk}"
  ents = lambda { |s| s.is_a?(Sketchup::Group) ? s.entities : s.definition.entities }
  # 1) 도너(정배율) 찾기
  donor = nil
  dw = nil
  asm = nil
  m.entities.each do |e|
    next unless e.is_a?(Sketchup::Group) || e.is_a?(Sketchup::ComponentInstance)
    asm = e if (e.respond_to?(:name) ? e.name.to_s : '') == 'SWD조립체_정배율_20260919'
  end
  if asm
    ents.call(asm).each do |s|
      next unless s.is_a?(Sketchup::Group) || s.is_a?(Sketchup::ComponentInstance)
      if (s.respond_to?(:name) ? s.name.to_s : '') == 'SWD_04_t9_240x1046'
        donor = s
        dw = asm.transformation * s.transformation
      end
    end
  end
  # 2) 커버 / 왜곡본 찾기
  cov = nil
  m.entities.each do |e|
    next unless e.is_a?(Sketchup::Group) || e.is_a?(Sketchup::ComponentInstance)
    cov = e if (e.respond_to?(:name) ? e.name.to_s : '') == '하부프레임커버'
  end
  oldp = nil
  oldw = nil
  if cov
    ents.call(cov).each do |s|
      next unless s.is_a?(Sketchup::Group) || s.is_a?(Sketchup::ComponentInstance)
      ents.call(s).each do |q|
        next unless q.is_a?(Sketchup::Group) || q.is_a?(Sketchup::ComponentInstance)
        if (q.respond_to?(:name) ? q.name.to_s : '') == 'SWD_04_t9_240x1046'
          oldp = q
          oldw = cov.transformation * s.transformation * q.transformation
        end
      end
    end
  end
  if donor.nil? || cov.nil? || oldp.nil?
    puts "STOP: donor=#{!donor.nil?} cover=#{!cov.nil?} old=#{!oldp.nil?}"
  else
    dpts = []
    coll = nil
    coll = lambda do |en, t|
      en.grep(Sketchup::Edge).each { |ed| ed.vertices.each { |v| dpts << v.position.transform(t) } }
      (en.grep(Sketchup::Group) + en.grep(Sketchup::ComponentInstance)).each { |q| coll.call(ents.call(q), t * q.transformation) }
    end
    coll.call(ents.call(donor), dw)
    dx = dpts.map { |p| p.x.to_mm }.minmax
    dy = dpts.map { |p| p.y.to_mm }.minmax
    dz = dpts.map { |p| p.z.to_mm }.minmax
    opts = []
    coll2 = nil
    coll2 = lambda do |en, t|
      en.grep(Sketchup::Edge).each { |ed| ed.vertices.each { |v| opts << v.position.transform(t) } }
      (en.grep(Sketchup::Group) + en.grep(Sketchup::ComponentInstance)).each { |q| coll2.call(ents.call(q), t * q.transformation) }
    end
    coll2.call(ents.call(oldp), oldw)
    ox = opts.map { |p| p.x.to_mm }.minmax
    oy = opts.map { |p| p.y.to_mm }.minmax
    oz = opts.map { |p| p.z.to_mm }.minmax
    puts "도너(정배율) 월드 X=#{dx.map { |v| v.round(1) }.inspect} Y=#{dy.map { |v| v.round(1) }.inspect} Z=#{dz.map { |v| v.round(1) }.inspect} (#{(dx[1] - dx[0]).round(1)}x#{(dy[1] - dy[0]).round(1)}x#{(dz[1] - dz[0]).round(1)})"
    puts "왜곡본  월드 X=#{ox.map { |v| v.round(1) }.inspect} Y=#{oy.map { |v| v.round(1) }.inspect} Z=#{oz.map { |v| v.round(1) }.inspect} (#{(ox[1] - ox[0]).round(1)}x#{(oy[1] - oy[0]).round(1)}x#{(oz[1] - oz[0]).round(1)})"
    # 3) 회전(Z 90도) 후 목표 위치 계산
    rz = Geom::Transformation.rotation(Geom::Point3d.new(0, 0, 0), Geom::Vector3d.new(0, 0, 1), 90.degrees)
    rp = dpts.map { |p| p.transform(rz) }
    rx = rp.map { |p| p.x.to_mm }.minmax
    ry = rp.map { |p| p.y.to_mm }.minmax
    rzz = rp.map { |p| p.z.to_mm }.minmax
    tcx = (ox[0] + ox[1]) / 2.0
    tcy = (oy[0] + oy[1]) / 2.0
    ttopz = oz[1]
    sh = Geom::Vector3d.new((tcx - (rx[0] + rx[1]) / 2.0).mm, (tcy - (ry[0] + ry[1]) / 2.0).mm, (ttopz - rzz[1]).mm)
    puts "검산: Z90 회전 후 크기 #{(rx[1] - rx[0]).round(1)}x#{(ry[1] - ry[0]).round(1)}x#{(rzz[1] - rzz[0]).round(1)} / 이동 dX=#{sh.x.to_mm.round(1)} dY=#{sh.y.to_mm.round(1)} dZ=#{sh.z.to_mm.round(1)}"
    puts "검산: 목표 중심 X#{tcx.round(1)} Y#{tcy.round(1)}, 상면 Z#{ttopz.round(1)} -> 예상 Z=[#{(ttopz - (rzz[1] - rzz[0])).round(1)},#{ttopz.round(1)}] (하판 상면 67.4보다 위)"
    wt = Geom::Transformation.translation(sh) * rz * dw
    ti = cov.transformation.inverse * wt
    m.start_operation('SWD_04 정배율 복제 안착', true)
    defn = donor.is_a?(Sketchup::Group) ? donor.entities.parent : donor.definition
    inst = cov.entities.add_instance(defn, ti)
    inst.name = 'SWD_04_t9_240x1046_정배율'
    oldp.hidden = true
    m.commit_operation
    np = []
    coll3 = nil
    coll3 = lambda do |en, t|
      en.grep(Sketchup::Edge).each { |ed| ed.vertices.each { |v| np << v.position.transform(t) } }
      (en.grep(Sketchup::Group) + en.grep(Sketchup::ComponentInstance)).each { |q| coll3.call(ents.call(q), t * q.transformation) }
    end
    coll3.call(inst.definition.entities, cov.transformation * inst.transformation)
    nx = np.map { |p| p.x.to_mm }.minmax
    ny = np.map { |p| p.y.to_mm }.minmax
    nz = np.map { |p| p.z.to_mm }.minmax
    tilt = nil
    best = 0.0
    inst.definition.entities.grep(Sketchup::Face).each do |fa|
      ps = fa.outer_loop.vertices.map { |v| v.position.transform(cov.transformation * inst.transformation) }
      next if ps.length < 3
      n = (ps[1] - ps[0]).cross(ps[2] - ps[0])
      next if n.length.to_f < 1.0e-12
      n.normalize!
      bb = Geom::BoundingBox.new
      ps.each { |p| bb.add(p) }
      ex = [bb.width.to_mm, bb.height.to_mm, bb.depth.to_mm].sort
      a = ex[1] * ex[2]
      if a > best
        best = a
        tilt = Math.acos([[n.z.abs, 1.0].min, -1.0].max) * 180.0 / Math::PI
      end
    end
    puts "== 신규 '#{inst.name}' scale=[#{inst.transformation.xscale.round(5)},#{inst.transformation.yscale.round(5)},#{inst.transformation.zscale.round(5)}]"
    puts "   월드 X=#{nx.map { |v| v.round(1) }.inspect} Y=#{ny.map { |v| v.round(1) }.inspect} Z=#{nz.map { |v| v.round(1) }.inspect} (#{(nx[1] - nx[0]).round(1)}x#{(ny[1] - ny[0]).round(1)}x#{(nz[1] - nz[0]).round(1)})"
    puts "   최대면 수평기울기=#{tilt ? tilt.round(4) : 'n/a'}deg (목표 0.000), 왜곡본 hidden=#{oldp.hidden?}"
    vw = m.active_view
    cam0 = vw.camera
    begin
      c = cov.bounds.center
      vw.camera = Sketchup::Camera.new(Geom::Point3d.new(c.x - 2500.mm, c.y - 3000.mm, c.z + 1500.mm), c, Geom::Vector3d.new(0, 0, 1))
      vw.zoom(cov)
      f = 'E:/도진팩토리/3D스캔및티칭시스템/_자동화/inbox/_step2_swd04.png'
      vw.write_image(f, 1600, 1000, true)
      puts "   캡처=#{f} 존재=#{File.exist?(f)}"
    rescue Exception => e3
      puts "   캡처 실패 #{e3.message}"
    ensure
      vw.camera = cam0
    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(6).join(" | ")
end
nil
