# encoding: UTF-8
# ① 돌기 없는 깨끗한 하판 신규 생성 후 교체 (기존 하판은 이름변경 + hidden, 삭제 안 함)
m = Sketchup.active_model
old = m.entities.grep(Sketchup::Group).find { |e| e.name == '조립부원판_20260919' }
raise "하판 없음" if old.nil?
tr = old.transformation
best=nil; ba=0.0
old.entities.grep(Sketchup::Face).each { |f| n=f.normal.transform(tr); next unless n.z<-0.05; if f.area>ba then ba=f.area; best=f end }
pa,pb,pc,pd = Geom.fit_plane_to_points(best.outer_loop.vertices.map{|v| v.position.transform(tr)})

outer = best.outer_loop.vertices.map { |v| v.position.transform(tr) }
notch = lambda do |p|
  xx = p.x.to_mm; yy = p.y.to_mm
  yy > 10731.95 && yy < 10951.0 && ((xx > 8899.0 && xx < 9001.0) || (xx > 9079.0 && xx < 9181.0))
end
keep = outer.reject { |p| notch.call(p) }
puts "외곽점 #{outer.size} -> #{keep.size} (돌기 자국 제거)"
holes = best.loops.reject { |l| l.outer? }.map { |l| l.vertices.map { |v| v.position.transform(tr) } }
puts "볼트구멍 #{holes.size}개"

m.start_operation('깨끗한 하판 생성/교체', true)
g2 = m.entities.add_group
fo = g2.entities.add_face(keep)
raise "외곽면 실패" if fo.nil?
holes.each { |hp| hf = g2.entities.add_face(hp); hf.erase! if hf && hf.valid? }
fo = g2.entities.grep(Sketchup::Face).max_by { |x| x.area }
puts "신규 하면 면적 = %.0f mm2 (기존 %.0f, 예상 +43,6xx)" % [fo.area*645.16, ba*645.16]
fo.reverse! if fo.normal.z > 0
fo.pushpull(-12.mm)
g2.name = '조립부원판_20260919'
old.name = '조립부원판_구_돌기포함_20260919'
old.hidden = true
m.commit_operation

b = g2.bounds
puts "신규하판 solid=#{g2.manifold?} vol=%.0fmm3" % (g2.volume.to_f*(25.4**3))
puts "bbox x %.2f..%.2f y %.2f..%.2f z %.2f..%.2f" % [b.min.x.to_mm,b.max.x.to_mm,b.min.y.to_mm,b.max.y.to_mm,b.min.z.to_mm,b.max.z.to_mm]
puts "구하판 hidden=#{old.hidden?} name=#{old.name}"
m.save
puts "SAVED #{File.mtime(m.path)}"
nil
