Why does a curve not create a face even though it completes the edges?

I have created four lines that close a loop, but they do not create a face. Can someone explain why and how to solve it? I can manually add a line on top of any of the created lines and the face will appear, but I would like it to be automatic.

i = 0
b = 10.mm
num = 10

grp = ent.add_group
gents = grp.entities

bl = [i,i*i,0]
tl = [i,i*i+b,0]
gents.add_line(tl,bl) # add the initial line

while i < num do
pti = [i,i*i,0] # first base point
ptix = [i,i*i+b,0] # first offset point
i += 1 # go to next step
ptj = [i,i*i,0] # next base point
ptjx = [i,i*i+b,0] # next offset point
gents.add_curve(pti,ptj) # add the base curve
gents.add_curve(ptix,ptjx) # add the offset curve
end

br = [i,i*i,0]
tr = [i,i*i+b,0]
gents.add_line(tr,br) # add the closing line

I have tried this

while i < num do
pti = [i,i*i,0] # first base point
ptix = [i,i*i+b,0] # first offset point
i += 1 # go to next step
ptj = [i,i*i,0] # next base point
ptjx = [i,i*i+b,0] # next offset point
gface = gents.add_face(pti,ptj,ptjx,ptix)
end

But this creates a face for each iteration, where I would need to erase each construction line instead. I hope there is a simpler solution.

Why does a polyline

SketchUp Polylines are special non-geometric path objects that are not yet exposed to the Ruby API.

You are speaking about Curves which are a series of connected edges thta can form any kind of shape. (Bezier, sine wave, freeform, etc.)

Technically, you created edges. Lines in the API are virtual geometric helper objects as described by the Geom module Overview.

I’ve always disliked the naming of the #add_line method.

Because they are not yet stitched together into a Loop object. Only (AFAIK) the #add_circle, #add_face and #add_ngon factory methods create a face inside a loop of edges.

The simplest way is to call #find_faces upon one of the edges.

Another way is to pass the curve’s edges into the #add_face factory method along with the other “loose” edges. Ie …

# If you know all the group's current edges will form a face loop:
gents.add_face(gents.grep(Sketchup::Edge))

But, … can we be sure that #grep will return the edges in the order that we want?
If you had kept references to the edges and curves that you created …

gents.add_face(efirst, *curve_edges.flatten, elast)
Your code with the changes ... (click to expand)
i = 0
b = 10.mm
num = 10

grp = ent.add_group
gents = grp.entities

bl = [i,i*i,0]
tl = [i,i*i+b,0]
efirst = gents.add_line(tl,bl) # add the initial line

curve_edges = []

while i < num do
  pti = [i,i*i,0] # first base point
  ptix = [i,i*i+b,0] # first offset point
  i += 1 # go to next step
  ptj = [i,i*i,0] # next base point
  ptjx = [i,i*i+b,0] # next offset point
  curve_edges << gents.add_curve(pti,ptj) # add the base curve
  curve_edges << gents.add_curve(ptix,ptjx) # add the offset curve
end

br = [i,i*i,0]
tr = [i,i*i+b,0]
# add the closing line
#elast = gents.add_line(tr,br) # error!
elast = gents.add_line(tr,tl) # always draw to the starting point

# create the face:
gents.add_face(efirst, *curve_edges.flatten, elast)
2 Likes

Thank you! That was a rapid response and a perfect answer. I couldn’t seem to make the #find_faces work, but the two other methods work flawlessly and I suppose the last method really is best practice. Greatly appreciated.

1 Like

Hmmm… a quick look makes me think that elast's 2nd point should be efirst's first point (tl) instead of whatever br evaluates as. This way you are sure to close the loop.

I assumed (you said you did) close the loop. (Edited the above example.)

1 Like