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/
Hello! It looks like you're interested in this conversation, but you don't have an account yet.
Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.
With your input, this post could be even better π
Register LoginAdvertisement