# 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
T,R = 12.0, 30.0
YMID=8142.55; mir=lambda{|y| 2*YMID-y}
SY0,SY1 = 7496.2, 8788.9
BOLTX=[3980.0,4075.0,4170.0,4265.0,4360.0]; YBL=7518.0
def dedup(p,t=1e-4); o=[]; p.each{|q| o<<q unless o.last && (o.last[0]-q[0]).abs<t && (o.last[1]-q[1]).abs<t}; o.pop if o.length>2 && (o.first[0]-o.last[0]).abs<t && (o.first[1]-o.last[1]).abs<t; o; end
def rrect(x0,x1,y0,y1,r,seg=8)
  p=[]; [[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{|cx,cy,a0,a1|
    (0..seg).each{|i| a=(a0+(a1-a0)*i/seg.to_f)*Math::PI/180.0; p<<[cx+r*Math.cos(a),cy+r*Math.sin(a)]}}; dedup(p)
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
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)
begin
  m.start_operation("조립부 원판", true)
  root=m.entities.add_group; root.name="조립부원판_20260919"
  e=root.entities
  e.add_face(rrect(uu.call(X0),uu.call(X1),SY0,SY1,R).map{|x,y| Geom::Point3d.new(x*MM,y*MM,0)})
  holes=0
  BOLTX.each{|x| [YBL, mir.call(YBL)].each{|y| e.add_face(circ(uu.call(x),y,9.0).map{|a,b| Geom::Point3d.new(a*MM,b*MM,0)}); holes+=1}}
  big=e.grep(Sketchup::Face).max_by{|f| f.area}
  e.grep(Sketchup::Face).to_a.each{|f| f.erase! if f.valid? && !f.equal?(big)}
  big.pushpull((big.normal.z>0 ? -T : T)*MM)
  root.transformation = trL
  m.commit_operation
  b=root.bounds
  puts "조립부원판 생성: solid=#{root.manifold?} 볼트구멍=#{holes}개 (M16 Ø18, 피치 95, Y=#{YBL}/#{mir.call(YBL)})"
  puts "  bbox (#{(b.min.x*25.4).round(1)},#{(b.min.y*25.4).round(1)},#{(b.min.z*25.4).round(1)})..(#{(b.max.x*25.4).round(1)},#{(b.max.y*25.4).round(1)},#{(b.max.z*25.4).round(1)})"
  puts "  판두께 #{T}T / 경사 #{(Math.atan(mL)*180/Math::PI).round(3)}deg 밀착면 / 하위그룹 #{root.entities.grep(Sketchup::Group).length}개(=평판)"
rescue Exception => ex
  m.commit_operation rescue nil
  puts "ERR #{ex.class}: #{ex.message}"
end
"PLATE1"
