# encoding: UTF-8
# 하부마운트커버_20260919  -- 단일 start/commit_operation, 기존 지오메트리 삭제 없음
m = Sketchup.active_model
ents = m.entities
MM = 1.0/25.4

# ---------- 순수 계산 (모델 미접촉) ----------
X0, X1 = 3855.0, 4410.0
YLo, YLi = 7496.2, 7562.2
YRi, YRo = 8722.9, 8788.9
ZTOP, T = 170.4, 12.0
ZDECK = ZTOP - T                      # 158.4
mL, xL0, zL0 = 0.1129672, 4423.8, 20.4
mR, xR0, zR0 = 0.1119904, 4415.1, 35.8
cL = 1.0/Math.sqrt(1+mL*mL)
cR = 1.0/Math.sqrt(1+mR*mR)
zL = lambda{|x| zL0 - mL*(x - xL0)}
BOLTX = [3900.0,3993.0,4086.0,4179.0,4272.0,4365.0]
YB_L, YB_R = 7518.0, 8767.0
HX0,HX1,HY0,HY1,HR = 4040.0,4240.0,7950.0,8330.0,30.0

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
  pts
end
def circ(cx,cy,r,n=24)
  (0...n).map{|i| a=2*Math::PI*i/n; [cx+r*Math.cos(a), cy+r*Math.sin(a)]}
end

uL = lambda{|x| (x-xL0)/cL}
uR = lambda{|x| (x-xR0)/cR}

# B_L (하판+좌플랜지) 로컬 윤곽
bl_outer = rrect(uL.call(X0), uL.call(X1), YLo, YRi, 25.0)
bl_holes = BOLTX.map{|x| circ(uL.call(x), YB_L, 9.0)}
bl_hatch = rrect(uL.call(HX0), uL.call(HX1), HY0, HY1, HR)
hu0,hu1 = uL.call(HX0)-25.0, uL.call(HX1)+25.0
hum = (hu0+hu1)/2.0
hy0,hy1 = HY0-25.0, HY1+25.0
hym = (hy0+hy1)/2.0
m12 = [[hu0,hy0],[hu0,hym],[hu0,hy1],[hum,hy0],[hum,hy1],[hu1,hy0],[hu1,hym],[hu1,hy1]].map{|a,b| circ(a,b,6.5)}

br_outer = rrect(uR.call(X0), uR.call(X1), YRi, YRo, 25.0)
br_holes = BOLTX.map{|x| circ(uR.call(x), YB_R, 9.0)}

d_outer = rrect(X0, X1, YLi, YRi, 25.0)
d_hatch = rrect(HX0, HX1, HY0, HY1, HR)

trL = Geom::Transformation.axes(Geom::Point3d.new(xL0*MM,0,zL0*MM),
        Geom::Vector3d.new(1,0,-mL).normalize, Geom::Vector3d.new(0,1,0),
        Geom::Vector3d.new(mL,0,1).normalize)
trR = Geom::Transformation.axes(Geom::Point3d.new(xR0*MM,0,zR0*MM),
        Geom::Vector3d.new(1,0,-mR).normalize, Geom::Vector3d.new(0,1,0),
        Geom::Vector3d.new(mR,0,1).normalize)
trD = Geom::Transformation.translation(Geom::Vector3d.new(0,0,ZDECK*MM))

# 세로판 (XZ 평면 쿼드, +Y 로 압출)
verts = [
  ["측판_L", 7562.2, 12.0,   [[X0,zL.call(X0)],[X1,zL.call(X1)],[X1,ZDECK],[X0,ZDECK]]],
  ["측판_R", 8710.9, 12.0,   [[X0,zL.call(X0)],[X1,zL.call(X1)],[X1,ZDECK],[X0,ZDECK]]],
  ["단부판_A",7574.2,1136.7, [[3855.0,zL.call(3855.0)],[3867.0,zL.call(3867.0)],[3867.0,ZDECK],[3855.0,ZDECK]]],
  ["단부판_B",7574.2,1136.7, [[4398.0,zL.call(4398.0)],[4410.0,zL.call(4410.0)],[4410.0,ZDECK],[4398.0,ZDECK]]],
  ["리브_1",  7574.2,1136.7, [[3990.0,zL.call(3990.0)],[4002.0,zL.call(4002.0)],[4002.0,ZDECK],[3990.0,ZDECK]]],
  ["리브_2",  7574.2,1136.7, [[4263.0,zL.call(4263.0)],[4275.0,zL.call(4275.0)],[4275.0,ZDECK],[4263.0,ZDECK]]],
]
puts "MATH OK  zL(#{X0})=#{zL.call(X0).round(2)} zL(#{X1})=#{zL.call(X1).round(2)}"
puts "tiltL=#{(Math.atan(mL)*180/Math::PI).round(3)}deg tiltR=#{(Math.atan(mR)*180/Math::PI).round(3)}deg"

# ---------- 모델 기록 ----------
log = []
begin
  m.start_operation("하부마운트커버_20260919", true)

  root = ents.add_group
  root.name = "하부마운트커버_20260919"

  mk = lambda do |name, outer, cuts, thick, tr|
    g = root.entities.add_group; g.name = name
    e = g.entities
    f = e.add_face(outer.map{|x,y| Geom::Point3d.new(x*MM, y*MM, 0)})
    main_area = f.area
    cuts.each{|lp| e.add_face(lp.map{|x,y| Geom::Point3d.new(x*MM, y*MM, 0)}) }
    e.grep(Sketchup::Face).each{|ff| ff.erase! if ff.valid? && ff.area < main_area*0.5 }
    big = e.grep(Sketchup::Face).select{|ff| ff.valid?}.max_by{|ff| ff.area}
    d = big.normal.z > 0 ? -thick : thick
    big.pushpull(d*MM)
    g.transformation = tr if tr
    log << "  #{name}: faces=#{g.entities.grep(Sketchup::Face).length} solid=#{g.manifold? rescue 'n/a'}"
    g
  end

  mk.call("하판_좌플랜지_12T", bl_outer, bl_holes + [bl_hatch] + m12, T, trL)
  mk.call("우플랜지_12T",     br_outer, br_holes,                    T, trR)
  mk.call("상판_12T",         d_outer,  [d_hatch],                   T, trD)

  verts.each do |name, y, wid, quad|
    g = root.entities.add_group; g.name = name
    f = g.entities.add_face(quad.map{|x,z| Geom::Point3d.new(x*MM, y*MM, z*MM)})
    d = f.normal.y > 0 ? wid : -wid
    f.pushpull(d*MM)
    log << "  #{name}: faces=#{g.entities.grep(Sketchup::Face).length} solid=#{g.manifold? rescue 'n/a'}"
  end

  # 기존 제안 부재 숨김 (삭제 금지)
  old = ents.grep(Sketchup::Group).find{|g| g.name == "윈치하부보강_제안_20260918"}
  if old && !old.hidden?
    old.hidden = true
    log << "  윈치하부보강_제안_20260918 -> hidden"
  elsif old
    log << "  윈치하부보강_제안_20260918 이미 hidden"
  end

  m.commit_operation
  bb = root.bounds
  puts "GROUP=#{root.name}"
  puts "BBOX mm min=(#{(bb.min.x*25.4).round(1)},#{(bb.min.y*25.4).round(1)},#{(bb.min.z*25.4).round(1)}) max=(#{(bb.max.x*25.4).round(1)},#{(bb.max.y*25.4).round(1)},#{(bb.max.z*25.4).round(1)})"
  puts "SUBGROUPS=#{root.entities.grep(Sketchup::Group).length}"
  puts log.join("\n")
  m.selection.clear; m.selection.add(root)
  m.active_view.zoom(root)
  puts "SELECTED=#{m.selection.length}"
rescue Exception => ex
  m.commit_operation rescue nil
  puts "BUILD ERROR: #{ex.class}: #{ex.message}"
  puts ex.backtrace[0,5].join("\n")
end
"BUILD1"
