Ruby question: create faces from edges? Faces with holes?
-
Hi all; can anybody explain what I'm doing wrong here? The documentation indicates that I can create a face from an array of edges, but it fails.
Now my real question is: how do I create a face with a hole in it.
[pre:3oekbghz]require 'sketchup.rb'
def foo_panel
entities = Sketchup.active_model.entitiesCreate a face from points
face = entities.add_face [[0,0,10], [20,0,10], [20,0,30], [0,0,30]]
puts faceCreate an array of edges from points
edges = entities.add_edges [[30,0,10], [50,0,10], [50,0,30],
[30,0,30], [30,0,10]]
puts edges.lengthCreate a face from that array of edges -- why does this fail?
face = entities.add_face(edges)
puts face
end[/pre:3oekbghz] -
Did you verify that
edges
really is an array ofSketchup::Edge
objects ?Sometimes the API dictionary errors have not been corrected.
If the array is correct, you can convert an array to a parameter list with the
*****
operator, like:
entities.add_face( *edges )
Also, you can use Edge#find_faces to create the faces(s) bounded by the edge arguments.
-
Also use this to be sure your acting within the current active editing context:
entities = Sketchup.active_model.active_entities
-
Assuming you have an array of just coplanar
edges
.
Make an array of all of the entities withents_in = edges[0].parent.entities.to_a
Now you iterate them and use;
edges.each{|edge| edge.find_faces }
Next get the new faces:
new_faces = (edges[0].parent.entities.to_a - ents_in).grep(Sketchup::Face)
You could then look through those and assuming the outer 'doughnut' has no connected faces the face with only one loop is a 'hole' ?
new_faces.each{|face| face.erase! unless face.loops[1] }
If you are 'creating' the loops of edges...
First make the faces in the hole[s] using..add_face(some_inner_edges)
[keep a reference to the face[s]], then make the doughnut face using..add_face(some_outer_edges)
: then finally erase the hole's face[s]. -
@dan rathbun said:
Also use this to be sure your acting within the current active editing context:
entities = Sketchup.active_model.active_entities
Thanks; I don't think that's the issue: the code I posted above is literally the entire ruby program and I'm executing it in an empty model.
I'll definitely try the suggestions you made above and see what happens.
-
Well, pretty much no joy on any of the suggestions here. Oddly enough, I found that manually retracing an edge only produced a face for certain edges. It's almost as if I was creating corrupt edges somehow.
I dumped the edges array, and it's definitely an array of four edges, all with endpoints exactly where they should be and all definitely co-planar.
I'm a little perplexed; this is almost the simplest possible test case for generating a face from edges. I can't imagine why it would fail. I'm also going to try creating the edges from Point3d objects and see if that makes a difference.
FWIW, I looked through all the plugins I've downloaded for SU and none of them generate faces from edges, they all do it from points.
-
I see your point having now replicated your code:
the ..add_face(edges) fails...
I never use it either...BUT there are ways of making a face from edges...
Collect the edges vertices, get a unique set and use those - vertices work as well as points in many such methods:
vs=[] edges.each{|e| vs << e.vertices } vs.flatten! vs.uniq! entities.add_face(vs)
-
I've replicated the problem in SU8 and SU2014 both. I think it's simply a bug in the ruby API. I suspect that nobody actually tries to create faces from edges.
The disturbing thing is, if I just create a square made out of edges, and retrace some of the edges by hand, I only get a face created if I retrace the last two edges. The first two don't work. It's as if the edges were corrupted somehow.
Anyway, I'm just going to go ahead and create faces from points. I can make a hole in the face using the technique you mentioned: create a face inside another face, then erase the inner face. It worked fine, so I'll just go with that.
-
The issue is that
edges = entities.add_edges [[30,0,10], [50,0,10], [50,0,30], [30,0,30], [30,0,10]]
doesn't weld the start and end point. Therefore there are two vertices at the same 3d point that isn't welded. add_face(edges) require the edges to form a closed loop - the edges you have in this case just looks to be closed.It's unexpected, I agree, but changing the behaviour now might break existing extensions.
But any reason for first creating edges and then creating the face from the edges instead of just creating the face with the points directly?
Advertisement