# encoding: UTF-8
# 하판 하면의 사다리꼴 돌출(지난 능선 자국) 2개 제거 -> 깨끗한 경사 평면
m = Sketchup.active_model
g = m.entities.grep(Sketchup::Group).find { |e| e.name == '조립부원판_20260919' }
raise "하판 없음" if g.nil?

# 0) 백업 사본
bk = "E:/도진팩토리/3D스캔및티칭시스템/_자동화/autosave/BACKUP_before_clean_#{Time.now.strftime('%Y%m%d_%H%M%S')}.skp"
m.save_copy(bk)
puts "backup=#{bk}"

tr = g.transformation
# 1) 가장 큰 하향면 = 하면 기준 평면
best = nil; bestA = 0.0
g.entities.grep(Sketchup::Face).each do |f|
  n = f.normal.transform(tr)
  next unless n.z < -0.05
  if f.area > bestA then bestA = f.area; best = f end
end
raise "하면 못찾음" if best.nil?
plane = Geom.fit_plane_to_points(best.outer_loop.vertices.map{|v| v.position.transform(tr)})
pa,pb,pc,pd = plane
zf = lambda { |x,y| -(pa*x + pb*y + pd) / pc }

bb = g.bounds
mg = 20.mm
x1 = bb.min.x - mg; x2 = bb.max.x + mg
y1 = bb.min.y - mg; y2 = bb.max.y + mg
p1 = Geom::Point3d.new(x1, y1, zf.call(x1,y1))
p2 = Geom::Point3d.new(x2, y1, zf.call(x2,y1))
p3 = Geom::Point3d.new(x2, y2, zf.call(x2,y2))
p4 = Geom::Point3d.new(x1, y2, zf.call(x1,y2))

m.start_operation('하판 하면 정리', true)
cut = m.entities.add_group
cf = cut.entities.add_face(p1,p2,p3,p4)
cf.reverse! if cf.normal.z > 0
cf.pushpull(400.mm)
puts "cutter solid=#{cut.manifold?} bbox z %.1f..%.1f" % [cut.bounds.min.z.to_mm, cut.bounds.max.z.to_mm]

vol_before = g.volume
res = g.subtract(cut)
if res.nil? || !res.valid?
  m.commit_operation
  puts "SUBTRACT 실패 res=#{res.inspect}"
else
  res.name = '조립부원판_20260919'
  m.commit_operation
  puts "OK solid=#{res.manifold?} vol %.0f -> %.0f mm3" % [vol_before.to_f*(25.4**3), res.volume.to_f*(25.4**3)]
  rb = res.bounds
  puts "bbox mm x %.2f..%.2f y %.2f..%.2f z %.2f..%.2f" % [rb.min.x.to_mm,rb.max.x.to_mm,rb.min.y.to_mm,rb.max.y.to_mm,rb.min.z.to_mm,rb.max.z.to_mm]
  rt = res.transformation
  cnt = 0
  res.entities.grep(Sketchup::Face).each { |f| n=f.normal.transform(rt); cnt+=1 if n.z < -0.05 }
  puts "하향면 개수(정리후)=#{cnt}"
end
nil
