Curved surfaces with Ruby
- 
 Hi, I'm trying to understand how to work with curved surfaces in SU using Ruby. I'd like to, for example, get an array of face objects that make up a surface. The API documentation seems very poor as it says that Faces are flat polygons, but when I select the outside of a cylinder, the Ruby console tells me it's a Face object. I tried using add_faces_from_mesh, but it just splits the surface into one of the component faces and the remaining surface, and returns 0. 
- 
 Make a cylinder. 
 Have View > Hidden Geometry OFF.
 Pick the curved part.
 It selects as one object.
 Entity Info says it's a 'Surface'.Deselect it. 
 Have View > Hidden Geometry ON.
 You can now see the facets making the surface.
 Pick a facet.
 Entity Info says it's a 'Face'.Faces that share common edge, where those edges are 'smooth' are part of a surface. 
 Within Sketchup when hidden geometry is 'off' these select as a single object, take materials as a single thing etc...Within Ruby a 'surface' is not very much accessible. 
 Its faces and edges etc are.
 There is one 'trick' surface using selections...
 selection.is_surface?
 This determines if the selection contains only all of the faces that are part of a single curved surface. Returns:
 True if the selection contains all of the faces that belong to a single curved surface.
 False if the selection does not contain all of the faces that belong to a single curved surface.Since a surface's faces are all connected and their shared edges are smooth? you can devise ways of getting all of the faces in a surface from one face in that surface... 
 What is the intention of your code ?
- 
 @tig said: Since a surface's faces are all connected and their shared edges are smooth? you can devise ways of getting all of the faces in a surface from one face in that surface... 
 What is the intention of your code ?I'd like to know: All the points/vertices that make the surface. 
 All the normals of the faces that make up the surface.I also want to be able to take a set of points and project them onto the surface, or rather find the intersection point between a ray and the surface. Your suggestion about connected faces is a bit vague. I would still need to be able to get one of the faces in the surface (without help from the user) and I don't know what makes an edge 'smooth'. 
- 
 Starting at the end... 
 Iterate the faces.
 edges=face.edges
 Iterate the edges
 edge.smooth?>> true or false
 An edge can also have .soft? and .hidden? true/false.
 To find all of the faces connected to a selected_face use
 connected_faces=selected_face.all_connected.find_all{|e|e.is_a?(Sketchup::Face)}
 To find all faces connected to the selected_face that are have a smooth edge and are thereby part of a common 'surface' you need to iterate the connected_faces in turn and their edges, testing foredge.smooth?and if so add that face to an array (which you kick off with surface=[selected_face]) unless it's already there, likesurface<<face unless surface.include?(face)assuming a test tells us it has a smooth common edge. As you collect faces then face=surface[-1] so you keep moving out from the first face until no more faces are available/connected-smoothly...
 How are you 'getting' the face ? You say you don't want help from the user, BUT there must be some clue to 'get' it 
 If the user is preselecting it and hidden-geometry is off then that selection consists of all connected faces anyway ? So thenselection.to_ashould be 'all connected faces' ??Once you have the faces then their vertices are easy to collect. 
 verts=[] faces.each{|f|verts<<f.vertices} verts.flatten.uniq!
 The array 'verts' is now all of the vertices used by the faces.Similarly the normals 
 normals=[] faces.each{|f|normals<<f.normal}If you make the surface as a group then 
 ray=model.raytest(point, vector)
 returns nil for a miss OR an array of a point and an array of what's been hit.
 To check that the hit is on the group useray[1].include?(group)which is true if the containing groups is hit.
 A typical hit 'ray' might be something like[point3d, [group,face]]
 The hit 'point' isray[0]
- 
 @tig said: selection.to_a should be 'all connected faces' ?? THAT's what I needed! Thanks! I should have probably spotted that before, but I made a silly mistake in my experimentations with the console and got myself thinking that when I selected a surface, Ruby thought the whole thing was just one face. 
- 
 If you want to get a Surface - identical to how SketchUp defines with - when Entity Info display Surface - based on faces connected by soft+smooth edges when this snippet works: http://forums.sketchucation.com/viewtopic.php?f=180&t=41211#p365381 
- 
 @thomthom said: If you want to get a Surface - identical to how SketchUp defines with - when Entity Info display Surface - based on faces connected by soft+smooth edges when this snippet works: http://forums.sketchucation.com/viewtopic.php?f=180&t=41211#p365381 Awesome! That snippet was exactly what I needed and it works great. Also glad to understand what soft and smooth edges are. Thanks a lot! 
- 
 @alexmojaki said: Also glad to understand what soft and smooth edges are. For a detailed breakdown of what each property does (soft and smooth has very distinct functions) check out this article: http://www.thomthom.net/thoughts/2012/06/soft-vs-smooth-vs-hidden-edges/ 
Advertisement


 
                             
                             
                             
                             
                             
                             
                            