🌓
搜索
 找回密码
 立即注册

SketchyBevel倒角插件,同时还可以补洞,安装后在右键菜单里.rb

admin 2022-7-23 23:27:56 16637
  1. require 'sketchup.rb'
  2. #SketchyBevel
  3. #Bevel all selected faces.
  4. #Adds a context menu item called Bevel
  5. #
  6. #
  7. #Copyright 2008 Chris Phillips
  8. module SketchyBevel
  9.     if($bevel_menu_loaded==nil)
  10.         $bevel_menu_loaded=true
  11.         
  12.         if(Sketchup.active_model.options["UnitsOptions"]["LengthUnit"]<2)
  13.             $bevelSettings = [1.0.inch, "true"]
  14.         else
  15.             $bevelSettings = [5.0.cm, "true"]
  16.         end           
  17.         UI.add_context_menu_handler { |menu|
  18.             selection=Sketchup.active_model.selection
  19.             
  20.             if(!selection.empty?)
  21.                 menu.add_item("Bevel"){            
  22.                     prompts = ["Amount","Cap Holes"]#,"Interations"]
  23.                     results = inputbox(prompts, $bevelSettings,["","true|false"], "Bevel selection")
  24.                     if (results)
  25.                         $bevelSettings=results
  26.                         Sketchup.active_model.selection.bevel(results[0],results[1])
  27.                     end
  28.                 }
  29.                 menu.add_item("Cap Holes"){
  30.                     Sketchup.active_model.start_operation("Cap Holes")               
  31.                     Sketchup.active_model.selection.cap_holes()
  32.                     Sketchup.active_model.commit_operation()
  33.                 }
  34.             end
  35.         }
  36.     end
  37.     class Sketchup::Selection
  38.         
  39.         def find_adjcent_coplaner_edges(edge,plane)
  40.             edges=[]
  41.             edge.vertices.each{|v|
  42.                 v.edges.each{|e|
  43.                     next if(e==edge)
  44.                     if(!e.get_attribute("SPCAP","used",false)&&
  45.                             e.start.position.on_plane?(plane)&& e.end.position.on_plane?(plane))
  46.                         edges.push(e)
  47.                         e.set_attribute("SPCAP","used",true)
  48.                         edges.push(find_adjcent_coplaner_edges(e,plane))
  49.                     end
  50.                 }
  51.             }
  52.             return edges.flatten
  53.                     
  54.         end
  55.         
  56.         def cap_holes()
  57.             self.faces.each{|f|
  58.                     f.edges.each{|e|e.delete_attribute("SPCAP","used")}
  59.                 }
  60.             
  61.             newfaces=[]
  62.             while(true)
  63.                 caps=[]
  64.                 self.faces.each{|f|
  65.                     f.edges.each{|e|
  66.                         if(e.faces.length<2)
  67.                             e.vertices.each{|v|
  68.                                 v.edges.each{|ve|
  69.                                     if(e!=ve && ve.faces.length<2 &&
  70.                                             !e.get_attribute("SPCAP","used",false) && !ve.get_attribute("SPCAP","used",false) )
  71.                                             
  72.                                             
  73.                                         #make face out of e and ve
  74.                                         #e.set_attribute("SPCAP","used",true)
  75.                                         #ve.set_attribute("SPCAP","used",true)
  76.                                         pts=[v.position,e.other_vertex(v).position,ve.other_vertex(v).position]
  77.                                         plane=Geom.fit_plane_to_points(pts)
  78.                                         ce=find_adjcent_coplaner_edges(ve,plane)
  79.                                         #ce.push(ve)
  80.                                         #puts ce.inspect
  81.                                         caps.push(ce)
  82.                                     end
  83.                                 }
  84.                             }
  85.                         end
  86.                     }
  87.                 }
  88.                 caps.each{|f|
  89.                     if(f.length==2)
  90.                         nf= [f[0].start.position.to_a,f[0].end.position.to_a,f[1].start.position.to_a,f[1].end.position.to_a].uniq
  91.                         #puts "tri"
  92.                         #puts nf.inspect
  93.                         newfaces.push(Sketchup.active_model.active_entities.add_face(nf))
  94.                     else
  95.                         #puts "quad"
  96.                         #puts f.inspect
  97. #puts f                        
  98. #cf=f.select{|tf|!tf.deleted?}
  99.                         newfaces.push(Sketchup.active_model.active_entities.add_face(f))
  100.                     end
  101.                 }
  102.                 #self.clear()
  103.                 #self.add(caps)
  104.                 #puts newfaces
  105.                 #self.add(newfaces) if(!newfaces.empty?)
  106.                 self.faces.each{|f|
  107.                     f.edges.each{|e|e.delete_attribute("SPCAP","used")}
  108.                 }
  109.                 puts caps.length
  110.                 break# if(caps.length==0)#found no caps so exit loop.
  111.                     
  112.             end               
  113.             return newfaces
  114.         end
  115.         def old_cap_holes()
  116.             newfaces=[]
  117.             while(true)
  118.                 caps=[]
  119.                 self.faces.each{|f|
  120.                     f.edges.each{|e|
  121.                         if(e.faces.length<2)
  122.                             e.vertices.each{|v|
  123.                                 v.edges.each{|ve|
  124.                                     if(e!=ve && ve.faces.length<2 &&
  125.                                             !e.get_attribute("SPCAP","used",false) && !ve.get_attribute("SPCAP","used",false) )
  126.                                         #make face out of e and ve
  127.                                         e.set_attribute("SPCAP","used",true)
  128.                                         ve.set_attribute("SPCAP","used",true)
  129.                                         caps.push([v.position,e.other_vertex(v).position,ve.other_vertex(v).position])
  130.                                     end
  131.                                 }
  132.                             }
  133.                         end
  134.                     }
  135.                 }
  136.                 caps.each{|f|newfaces.push(Sketchup.active_model.active_entities.add_face(f))}
  137.                 self.add(newfaces)
  138.                 self.faces.each{|f|
  139.                     f.edges.each{|e|e.delete_attribute("SPCAP","used")}
  140.                 }
  141.                 puts caps.length
  142.                 break if(caps.length==0)#found no caps so exit loop.
  143.                     
  144.             end               
  145.             return newfaces
  146.         end
  147.         
  148.         
  149.         def bevel(amount,bCapHoles)
  150.             Sketchup.active_model.start_operation("Bevel")
  151.             
  152.             #build a nested array of faces[edges[verts]]
  153.             allFaces=self.faces.collect{|f|
  154.                 verts=f.outer_loop.vertices
  155.                 edges=[]
  156.                 i=0
  157.                 while i<verts.length
  158.                     edges.push([verts[i].position,verts[(i+1)%verts.length].position])
  159.                     i=i+1
  160.                 end
  161.                 edges
  162.             }
  163.             #make a simple array of all the points        
  164.             allPoints=allFaces.flatten
  165.             #find any duplicate points. These points will make cap faces later.
  166.             dupePoints=allPoints.collect{|p|allPoints.select{|p2|p==p2}}
  167.             
  168.             #simple array of all edges
  169.             allEdges=[]
  170.             allFaces.each{|f|
  171.                 f.each{|edge|allEdges.push(edge)}
  172.             }
  173.             
  174.             #find overlapping edges. Each will be a bevel face
  175.             dupeEdges=[]
  176.             allEdges.each_with_index{|e,i|
  177.                 allEdges.each_with_index{|e2,i2|
  178.                     if(i!=i2&& (e[0]==e2[0]&&e[1]==e2[1])||(e[1]==e2[0]&&e[0]==e2[1]))
  179.                         dupeEdges.push([e,e2])
  180.                     end
  181.                 }
  182.             }
  183.             
  184.             shrunkFaces=[]
  185.             #Create a shrunken version of each face
  186.             allFaces.each{|f|
  187.                 SketchyBevel::shrink_face(f,amount)
  188.                 pts=f.collect{|edge|edge[0]}
  189.                 shrunkFaces.push(Sketchup.active_model.active_entities.add_face(pts))
  190.             }
  191.             #Create the bevel. A 4 sided polygon made from each formerly overlapping edge
  192.             newFaces=[]
  193.             dupeEdges.each{|edge|
  194.                 newFaces.push(Sketchup.active_model.active_entities.add_face(edge.flatten))
  195.             }
  196.             
  197. bCapHoles="false"
  198.             #~ caps=[]
  199.             #~ capEdges=newFaces.each{|f|
  200.                 #~ f.edges.each{|e|
  201.                     #~ if(e.faces.length<2)
  202.                         #~ e.vertices.each{|v|
  203.                             #~ v.edges.each{|ve|
  204.                                 #~ if(!e.get_attribute("SPBEVEL","alreadybeveled",false) &&
  205.                                     #~ !ve.get_attribute("SPBEVEL","alreadybeveled",false) && e!=ve && ve.faces.length<2)
  206.                                     #~ #make face out of e and ve
  207.                                     #~ e.set_attribute("SPBEVEL","alreadybeveled",true)
  208.                                     #~ ve.set_attribute("SPBEVEL","alreadybeveled",true)
  209.                                     #~ caps.push([v.position,e.other_vertex(v).position,ve.other_vertex(v).position])
  210.                                 #~ end
  211.                             #~ }
  212.                         #~ }
  213.                     #~ end
  214.                     #~ }
  215.                 #~ }
  216.                
  217.             #~ caps.each{|f|Sketchup.active_model.entities.add_face(f)}
  218.             #capEdges=newFaces.collect{|f|
  219.             #    f.edges.select{|e|e.faces.length<2}
  220.             #    }
  221.             #puts "caps"
  222.             #puts capEdges.inspect
  223.             
  224.             #~ #cap the corners by drawing a face around each formerly duplicated point.
  225.             dupePoints.each{|pts|
  226.                 #remove any duplicated points.
  227.                 tpts=pts.collect{|p|p.to_a}.uniq
  228.                 case tpts.length
  229.                 when 3
  230.                     Sketchup.active_model.active_entities.add_face(tpts)
  231.                 when 4
  232.                     0.upto(tpts.length-2){|i|
  233.                         tri=[tpts[i],tpts[(i+1)%tpts.length],tpts[(i+2)%tpts.length]]
  234.                         Sketchup.active_model.active_entities.add_face(tri)   
  235.                     }   
  236.                
  237.                     #Sketchup.active_model.entities.add_face(tpts[0],tpts[1],tpts[2])
  238.                     #Sketchup.active_model.entities.add_face(tpts[1],tpts[2],tpts[3])
  239.                     #ca=(tpts[2]-tpts[1]).cross(tpts[3]-tpts[2])
  240.                     #if((tpts[3]-tpts[2]).cross(tpts[0]-tpts[3]).dot(ca)<0.0)
  241.                         #Sketchup.active_model.entities.add_face(tpts[2],tpts[3],tpts[0])
  242.                     #else
  243.                         #Sketchup.active_model.entities.add_face(tpts[1],tpts[3],tpts[0])
  244.                     #end
  245.                     #Sketchup.active_model.entities.add_face(tpts.slice(0,3))
  246.                 end
  247.             } if(bCapHoles=="true")
  248.             #remove all the old geometry.
  249.             Sketchup.active_model.selection.each{|e|e.erase!}
  250.             
  251.             Sketchup.active_model.selection.add(shrunkFaces)            
  252.             Sketchup.active_model.selection.add(newFaces)
  253.             Sketchup.active_model.selection.add(cap_holes())
  254.             Sketchup.active_model.commit_operation()
  255.         end
  256.         def faces()
  257.             self.select{|s|s.class==Sketchup::Face}   
  258.         end
  259.     end
  260.    
  261.    
  262.     def self.shrink_face(face,amount)
  263.         
  264.         #TODO.face is really edges[].
  265.         
  266.         
  267.         normal=(face.first[1]-face.first[0]).cross(face.last[1]-face.last[0]).normalize
  268.         if(normal.length==0)
  269.             plane=Geom.fit_plane_to_points([face[0][0],face[0][1],face[1][0],face[1][1],face[2][0],face[2][1]])
  270.             puts normal
  271.             normal=Geom::Vector3d.new(plane[0],plane[1],plane[2])
  272.             puts normal
  273.         end
  274.         #normal=face.normal
  275.         #Sketchup.active_model.entities.add_line(face.first[0],face.first[0]+normal)
  276.         
  277.         #find the direction to move each vert in face
  278.         shrinkVectors=[]
  279.         lastEdge=face.last #use last vert in face is connected to the first vert in face.
  280.         face.each{|edge|
  281.             #create 2 vectors from each edge
  282.             va=lastEdge[0]-lastEdge[1]
  283.             vb=edge[1]-edge[0]
  284.             lastEdge=edge #use this next loop.
  285.             #find angle between the two vectors.        
  286.             if(va.cross(vb).dot(normal)<0) #check to see if angle >180
  287.                 angle=(360.degrees-va.angle_between(vb)) #angle is >180
  288.             else
  289.                 angle=va.angle_between(vb)
  290.             end
  291.             #rotate one vector 1/2 the angle between the two edges
  292.             sv=va.transform(Geom::Transformation.new([0,0,0],normal,angle/2))
  293.             #set the distance to move based on the amount of bevel.
  294.             sv.length=amount/Math.sin(angle/2)
  295.             #save.
  296.             shrinkVectors.push(sv)
  297.         }
  298.         
  299.         edge=face[0]
  300.         before=(edge[0]-edge[1]).length
  301.         after=(edge[0].transform(shrinkVectors[0])-edge[1].transform(shrinkVectors[1])).length
  302.         
  303.         
  304.         bFlipped=false
  305.         #~ if(edge[0]!=edge[1]&& (edge[0].transform(shrinkVectors[0])-edge[1].transform(shrinkVectors[1])).length>before)
  306.             #~ bFlipped=true
  307.         #~ end
  308.         
  309.         #now move each edge by the amount calculated. This actually shrinks the face.
  310.         face.each_index{|index|
  311.             edge=face[index]
  312.             if(!bFlipped)
  313.                 edge[0].transform!(shrinkVectors[index])
  314.                 edge[1].transform!(shrinkVectors[(index+1)%face.length])
  315.             else
  316.                 edge[0].transform!(shrinkVectors[index].reverse)
  317.                 edge[1].transform!(shrinkVectors[(index+1)%face.length].reverse)
  318.             end
  319.         }
  320.     end
  321. end
复制代码


扫一扫

0 回复

高级模式
游客
返回顶部