# encoding: UTF-8
m = Sketchup.active_model
MM = 1.0/25.4
mL, xL0, zL0 = 0.1129672, 4423.8, 20.4
cL = 1.0/Math.sqrt(1+mL*mL)
uu = lambda{|x| (x-xL0)/cL}
X0, X1 = 3940.0, 4410.0
U0, U1 = uu.call(X0), uu.call(X1)
YMID = 8142.55
SPY = [8117.55, 8167.55]
RIBX = [[3965.0,4005.0],[4020.0,4060.0],[4290.0,4330.0],[4350.0,4390.0]]
RIBY = [[7540.0, SPY[0]],[SPY[1], 8745.1]]
LIPY = [[7496.2,7506.2],[8778.9,8788.9]]
ZB, DR, DL = -12.0, 25.0, 30.0

def dedup(pts, tol=1e-4)
  out=[]
  pts.each{|p| out << p unless out.last && (out.last[0]-p[0]).abs<tol && (out.last[1]-p[1]).abs<tol}
  out.pop if out.length>2 && (out.first[0]-out.last[0]).abs<tol && (out.first[1]-out.last[1]).abs<tol
  out
end
def rrect(x0,x1,y0,y1,r,seg=8)
  pts=[]
  [[x1-r,y0+r,-90.0,0.0],[x1-r,y1-r,0.0,90.0],[x0+r,y1-r,90.0,180.0],[x0+r,y0+r,180.0,270.0]].each do |cx,cy,a0,a1|
    (0..seg).each{|i| a=(a0+(a1-a0)*i/seg.to_f)*Math::PI/180.0; pts << [cx+r*Math.cos(a), cy+r*Math.sin(a)]}
  end
  dedup(pts)
end
root = m.entities.grep(Sketchup::Group).find{|g| g.name=="하부마운트커버_v2_20260919"}
plan = []
plan << ["능선_척추", rrect(U0,U1,SPY[0],SPY[1],25.0), DR]
RIBX.each_with_index do |(xa,xb),i|
  RIBY.each_with_index do |(ya,yb),j|
    plan << ["능선_늑골_#{i+1}#{j==0 ? 'L':'R'}", rrect(uu.call(xa),uu.call(xb),ya,yb,20.0), DR]
  end
end
LIPY.each_with_index{|(ya,yb),i| plan << ["가장자리립_#{i==0 ? 'L':'R'}", rrect(U0,U1,ya,yb,5.0), DL]}
puts "plan=#{plan.length} pts=#{plan.map{|a,b,c| b.length}.inspect}"
begin
  m.start_operation("v2 등껍질 리브", true)
  made=[]
  plan.each do |nm, outer, d|
    g = root.entities.add_group; g.name = nm
    f = g.entities.add_face(outer.map{|x,y| Geom::Point3d.new(x*MM,y*MM,ZB*MM)})
    f.pushpull((f.normal.z > 0 ? -d : d)*MM)
    made << [nm, g.manifold?]
  end
  m.commit_operation
  puts "  made=#{made.length} nonsolid=#{made.reject{|n,s| s}.map{|n,s| n}.inspect}"
rescue Exception => ex
  m.commit_operation rescue nil
  puts "ERR #{ex.class}: #{ex.message}"
end
# 실제 꼭짓점 기준 세계 bbox (AABB-of-AABB 부풀림 배제)
tr = root.transformation
mn=[1e9]*3; mx=[-1e9]*3
root.entities.grep(Sketchup::Group).each do |g|
  g.entities.grep(Sketchup::Face).each{|f| f.vertices.each{|v|
    p = v.position.transform(g.transformation*tr)
    3.times{|k| val=[p.x,p.y,p.z][k]*25.4; mn[k]=val if val<mn[k]; mx[k]=val if val>mx[k]} }}
end
puts "REAL BBOX mm (#{mn.map{|v| v.round(1)}.join(',')}) .. (#{mx.map{|v| v.round(1)}.join(',')})"
puts "SUBGROUPS=#{root.entities.grep(Sketchup::Group).length} nonsolid=#{root.entities.grep(Sketchup::Group).reject{|g| g.manifold?}.map{|g| g.name}.inspect}"
ys=[]
root.entities.grep(Sketchup::Group).each{|g| g.entities.grep(Sketchup::Face).each{|f| f.vertices.each{|v| ys << (v.position.transform(g.transformation).y*25.4).round(2)}}}
ys.uniq!
puts "SYMMETRY uniqueY=#{ys.length} mismatch=#{ys.reject{|y| ys.any?{|o| ((2*YMID-y)-o).abs<0.05}}.length}"
"V2D"
