# encoding: UTF-8
begin
  puts "###DZW-WIRE-ONEPIECE-20260920"
  m = Sketchup.active_model
  bk = 'E:/도진팩토리/3D스캔및티칭시스템/_자동화/autosave/BACKUP_before_wire.skp'
  m.save_copy(bk)
  puts "BACKUP=#{bk}"
  faces = m.selection.grep(Sketchup::Face)
  if faces.length < 10
    puts "STOP: 선택 면 #{faces.length}개 -> 중단"
  else
    pts = []
    faces.each { |f| f.outer_loop.vertices.each { |v| pts << v.position } }
    xs = pts.map { |p| p.x.to_mm }
    ys = pts.map { |p| p.y.to_mm }
    zs = pts.map { |p| p.z.to_mm }
    dim = [xs.max - xs.min, ys.max - ys.min, zs.max - zs.min]
    ax = dim.index(dim.max)
    puts "면 #{faces.length}개 / 정점 #{pts.length}개, bbox=[#{dim[0].round(1)},#{dim[1].round(1)},#{dim[2].round(1)}] 주축=#{%w[X Y Z][ax]}"
    key = lambda { |p| [p.x.to_mm, p.y.to_mm, p.z.to_mm][ax] }
    lo = pts.map { |p| key.call(p) }.min
    hi = pts.map { |p| key.call(p) }.max
    nb = 48
    w = (hi - lo) / nb
    bins = Array.new(nb) { [] }
    pts.each do |p|
      i = ((key.call(p) - lo) / w).floor
      i = nb - 1 if i >= nb
      i = 0 if i < 0
      bins[i] << p
    end
    cps = []
    bins.each_with_index do |bp, i|
      next if bp.length < 6
      cx = bp.map { |p| p.x.to_f }.inject(:+) / bp.length
      cy = bp.map { |p| p.y.to_f }.inject(:+) / bp.length
      cz = bp.map { |p| p.z.to_f }.inject(:+) / bp.length
      c = Geom::Point3d.new(cx, cy, cz)
      rr = bp.map { |p| c.distance(p).to_mm }
      rr.sort!
      med = rr[rr.length / 2]
      cps << [i, c, med, bp.length]
    end
    if cps.length < 4
      puts "STOP: 유효 구간 #{cps.length}개 -> 중단"
    else
      rs = cps.map { |a| a[2] }.sort
      rmed = rs[rs.length / 2]
      dia = (2.0 * rmed).round(1)
      puts "검산: 구간 #{cps.length}개, 반경 중앙값 #{rmed.round(2)}mm -> 추정 지름 #{dia}mm (허용 10~30)"
      keep = cps.select { |a| a[2] <= rmed * 1.8 }
      puts "검산: 후크/이형 구간 제외 #{cps.length - keep.length}개 (반경 > #{(rmed * 1.8).round(1)}mm)"
      if dia < 8.0 || dia > 40.0
        puts "STOP: 추정 지름 #{dia}mm 이 상식 범위 밖 -> 생성 중단(모델 무수정)"
      elsif keep.length < 4
        puts "STOP: 유효 경로점 부족 -> 중단"
      else
        path = keep.map { |a| a[1] }
        sm = []
        path.each_with_index do |p, i|
          if i == 0 || i == path.length - 1
            sm << p
          else
            a = path[i - 1]
            b = path[i + 1]
            sm << Geom::Point3d.new((a.x + 2 * p.x + b.x) / 4.0, (a.y + 2 * p.y + b.y) / 4.0, (a.z + 2 * p.z + b.z) / 4.0)
          end
        end
        len = 0.0
        (0...(sm.length - 1)).each { |i| len += sm[i].distance(sm[i + 1]).to_mm }
        puts "검산: 경로점 #{sm.length}개, 경로 길이 #{len.round(1)}mm"
        puts "검산: 시작 #{sm[0].to_a.map { |v| v.to_mm.round(1) }.inspect} 끝 #{sm[-1].to_a.map { |v| v.to_mm.round(1) }.inspect}"
        m.start_operation('윈치와이어 일체 생성', true)
        g = m.active_entities.add_group
        cur = g.entities.add_curve(sm)
        d0 = sm[1] - sm[0]
        d0.normalize!
        circ = g.entities.add_circle(sm[0], d0, rmed.mm, 16)
        fa = g.entities.add_face(circ)
        okmade = false
        begin
          fa.followme(cur)
          okmade = true
        rescue Exception => ef
          puts "   followme 실패: #{ef.class}: #{ef.message}"
        end
        if okmade
          g.name = '윈치와이어_일체_20260920'
          m.commit_operation
          b = g.bounds
          nf = g.entities.grep(Sketchup::Face).length
          puts "== '#{g.name}' 면수=#{nf} 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}"
          bad = (b.min.x.to_mm < xs.min - 60) || (b.max.x.to_mm > xs.max + 60) ||
                (b.min.y.to_mm < ys.min - 60) || (b.max.y.to_mm > ys.max + 60) ||
                (b.min.z.to_mm < zs.min - 60) || (b.max.z.to_mm > zs.max + 60)
          if bad || nf < 4
            m.start_operation('와이어 롤백', true)
            g.erase!
            m.commit_operation
            puts "   생성 결과가 원본 범위를 벗어남 -> 즉시 롤백, 저장 안 함"
          else
            vw = m.active_view
            cam0 = vw.camera
            begin
              c = b.center
              [['iso', Geom::Point3d.new(c.x - 4000.mm, c.y - 5000.mm, c.z + 2500.mm)],
               ['side', Geom::Point3d.new(c.x, c.y - 7000.mm, c.z + 500.mm)]].each do |tag, eye|
                vw.camera = Sketchup::Camera.new(eye, c, Geom::Vector3d.new(0, 0, 1))
                vw.zoom_extents
                f = "E:/도진팩토리/3D스캔및티칭시스템/_자동화/inbox/_wire_#{tag}.png"
                vw.write_image(f, 1600, 1000, true)
                puts "   캡처 #{tag}=#{f} 존재=#{File.exist?(f)}"
              end
            rescue Exception => e3
              puts "   캡처 실패 #{e3.message}"
            ensure
              vw.camera = cam0
            end
            puts "   기존 648면 hidden 처리는 건너뜀(후크 면 구분 불확실 -> 원본 무손상 유지)"
            ok = m.save
            puts "SAVE=#{ok.inspect} modified?=#{m.modified?.inspect}"
          end
        else
          g.erase! if g.valid?
          m.commit_operation
          puts "   생성 실패 -> 변경 없음"
        end
        puts "DONE"
      end
    end
  end
rescue Exception => e
  puts "EXC #{e.class}: #{e.message}"
  puts e.backtrace.first(6).join(" | ")
end
nil
