# How do I close / create a face?

HI all,

I’ve just started with Ruby for sketchup. I’m creating a rotary encoder which works fine, but the faces won’t close when created by Ruby.

I’m creating an outer and inner arcs with

edgearray = entities.add_arc centre, xaxis, normal, \$r1/25.4, start_a, end_a, facets
edge = edgearray[0]
arccurve = edge.curve
end_angle = arccurve.end_angle

#################################################
edgearray = entities.add_arc centre, xaxis, normal, \$r2/25.4, start_a, end_a, facets
edge = edgearray[0]
arccurve = edge.curve

and closing the face with

##################################################
# Now create the closing lines at the start of arc
point1 = Geom::Point3d.new(Math.cos(((360.0 / segments) *( segment )) * (Math::PI / 180)) * \$r2 / 25.4, Math.sin(((360.0 / segments) *( segment)) * (Math::PI / 180)) * \$r2 / 25.4,0) # Outer arc
point2 = Geom::Point3d.new(Math.cos(((360.0 / segments) *( segment )) * (Math::PI / 180)) * \$r1 / 25.4, Math.sin(((360.0 / segments) *( segment)) * (Math::PI / 180)) * \$r1 / 25.4,0) # Inner arc
##################################################
# Now create the closing lines at the end of arc
point1 = Geom::Point3d.new(Math.cos(((360.0 / segments) *( segment + 1)) * (Math::PI / 180)) * \$r2 / 25.4, Math.sin(((360.0 / segments) *( segment + 1)) * (Math::PI / 180)) * \$r2 / 25.4,0) # Outer arc
point2 = Geom::Point3d.new(Math.cos(((360.0 / segments) *( segment + 1)) * (Math::PI / 180)) * \$r1 / 25.4, Math.sin(((360.0 / segments) *( segment + 1)) * (Math::PI / 180)) * \$r1 / 25.4,0) # Inner arc

Everything joins up nicely, but no faces. If I then manually draw a line over the scripted line, the face completes, but I need to do it iin code as there’s literally thousands of faces.

Pick one of the drawn Edges and call find_faces.

http://www.sketchup.com/intl/en/developer/docs/ourdoc/edge#find_faces

Thanks Jim.
I’ve been working with the code, but having some difficulty with the arcs. Any ideas on how to use this method with arcs?

An arc is actually a series of Edges in SketchUp. Get ahold of one of the Edges and use find_faces on it.

Thanks slbaumgartner,

I’ve been trying the example (Homepage | SketchUp Developer), and trying to select just one line.

What I’m trying to achieve is this:

If I try to select just one of the joining the arcs, I get ‘Error: #<TypeError: wrong argument type Sketchup::Edge (expected Array)>’.
When I draw a box around it, I get a face from that box, but not the arc.

I’m pulling my hair out here!

I wasn’t able to post the second image, but this is what my code creates

You haven’t given us all of the code…
But can I suggest you step back… and make a method to draw two arcs at a given spec (entities, center, axis, normal, rad1, rad2, start_angle, end_angle) and draw two additional edges between the arcs’ start-vertices and end-vertices.: you have the arrays of all arc-edges and the two end edges, just use edge.find_face on that last edge… Temporary grouping ensures no geometry clashes…
Here my example:

module TIG
ents=Sketchup.active_model.active_entities unless ents
ents=grop.entities
vx10=arc1[0].start
vx20=arc2[0].start
vx12=arc1[-1].end
vx22=arc2[-1].end
edg2.find_faces
face=ents.grep(Sketchup::Face)
grop.explode
return face
end
end

To use it = TIG.arcfaces(list_of_parameters)
Pass nil if a default is OK…
Just call the method with different parameters to make different arc-sets.
The method returns the face that was added…
So it you want to pushpull it later you can [remember because of the arcs’ configurations and the resulting face a -ve distance will be ‘up’]…
Repeat as desired with different radii etc…

2 Likes

Thanks TIG, that’s awesome!

The one thing that I can’t work out though is the bigger arcs - they’re either 2 or 3 segments and ‘notchy’. i can’t think of a better way to put it!

The small arcs work a treat.

I’m not asking that you do all of my work for me, but I just can’t see how to the number of entities higher to fix the larger arcs.

I can’t for whatever reason post all of the code as this editor seems to confuse ends / comments with markup.

Thanks mate,
Shane

Sorry, I’ve worked out how to post the full code.

module TIG
ents=Sketchup.active_model.active_entities unless ents
ents=grop.entities
vx10=arc1[0].start
vx20=arc2[0].start
vx12=arc1[-1].end
vx22=arc2[-1].end
edg2.find_faces
face=ents.grep(Sketchup::Face)
grop.explode
return face
end
end

########################################################################
#
# This script will create the layout for my absolute rotary encoder
# This will be used in the construction of my telescope.
# Written by Shane Frost
# 13 Nov 2014
#
# TODO
#
########################################################################

# Begin by declaring the variables
ring = 1
rings = 10
\$r1 = 250
segments = 2.0
facets = 40
x = 0
y = 0
mountOffset = 15

#######################################################
centre_point = Geom::Point3d.new(x,y,0)
normal_vector = Geom::Vector3d.new(x,y,1)
radius = (\$r1 - mountOffset) / 25.4

entities = Sketchup.active_model.entities
first_edge = edgearray[0]
arccurve = first_edge.curve

# Loop through the rings.
while ring < rings + 1 do

#Increment the radius by 10mm and reset the segment back to the first
\$r2 = \$r1 + 10
segment = 0
AngleVal = 360.0 / segments

#Loop through the segments of the ring
while segment < segments do
# Create an segment arc, normal to the Z axis
centre = Geom::Point3d.new
normal = Geom::Vector3d.new 0,0,1
xaxis = Geom::Vector3d.new 1,0,0
start_a = Math::PI * 2 / segments * segment
end_a =  Math::PI * 2 / segments * (segment +1)
model = Sketchup.active_model
entities = model.entities
edgearray = entities.add_arc centre, xaxis, normal, \$r1/25.4, start_a, end_a, facets
edge = edgearray[0]
arccurve = edge.curve
end_angle = arccurve.end_angle

#################################################
edgearray = entities.add_arc centre, xaxis, normal, \$r2/25.4, start_a, end_a, facets
edge = edgearray[0]
arccurve = edge.curve

##################################################
# Now create the closing lines at the start of arc
point1 = Geom::Point3d.new(Math.cos(((360.0 / segments) *( segment )) * (Math::PI / 180)) * \$r2 / 25.4, Math.sin(((360.0 / segments) *( segment)) * (Math::PI / 180)) * \$r2 / 25.4,0) # Outer arc
point2 = Geom::Point3d.new(Math.cos(((360.0 / segments) *( segment )) * (Math::PI / 180)) * \$r1 / 25.4, Math.sin(((360.0 / segments) *( segment)) * (Math::PI / 180)) * \$r1 / 25.4,0) # Inner arc
##################################################
# Now create the closing lines at the end of arc
point1 = Geom::Point3d.new(Math.cos(((360.0 / segments) *( segment + 1)) * (Math::PI / 180)) * \$r2 / 25.4, Math.sin(((360.0 / segments) *( segment + 1)) * (Math::PI / 180)) * \$r2 / 25.4,0) # Outer arc
point2 = Geom::Point3d.new(Math.cos(((360.0 / segments) *( segment + 1)) * (Math::PI / 180)) * \$r1 / 25.4, Math.sin(((360.0 / segments) *( segment + 1)) * (Math::PI / 180)) * \$r1 / 25.4,0) # Inner arc

##################################################
# Find the faces
# Thanks to TIG from Sketchup Forums!

segment += 2 #Increment the segment
end

# Now increment the required variables before moving to the next ring.
ring += 1
\$r1 += 10
segments += segments
facets -= 2
end

#######################################################
# Finish off by closing the outside of the disc.
centre_point = Geom::Point3d.new(x,y,0)
normal_vector = Geom::Vector3d.new(x,y,1)
entities = Sketchup.active_model.entities
first_edge = edgearray[0]
arccurve = first_edge.curve

No matter how it looks, all arcs in SketchUp are actually series of straight Edge segments: Entities#add_arc has an optional sixth argument that sets the number of segments in the arc. Increasing it from the default will make the curves look smoother.

1 Like

Thanks slbaumgartner, you are of course correct! I’ve added a parameter for the number of faces and all is well with the world.

My many thanks to jim_foltz, TIG & slbaumgartner for your invaluable assistance.

I will throw the finished code on github for anybody that wishes to use it.

Yes the default is used if you don’t pass a final ‘numsegs’.
The modified method would be something like:

module TIG
ents=Sketchup.active_model.active_entities unless ents
ents=grop.entities
vx10=arc1[0].start
................

It defaults to 12 segments if nil is passed to the method.
Before calling the method you can calculate the integer equivalent to say 1 for each degree of swept arc and give your arc that numseg [OR 2 if <2] ?

That’s a great idea TIG.

Cheers.

def arc()
ents=Sketchup.active_model.active_entities unless ents
ents=grop.entities
cent=[0, 0, 0]
axis=[0,0,-1]
norm=[1, 0, 0]
stara=90.degrees
enda=270.degrees
accr=100

vx10=arc1[0].start
vx12=arc1[-1].end

edg1.find_faces
face=ents.grep(Sketchup::Face)
grop.explode
return face
end

def torus()
model = Sketchup.active_model
entities = model.active_entities
face=arc()
cent=[0, 30, 0]
axis_1=[0,-1,0]
normal_1=[0, 0, 1]
edg2=entities.add_arc cent, axis_1, normal_1, 30, 0.degrees, 180.degrees, 100
st=face.followme(edg2)
return st
end

I am trying to make a torus (google it) I repurposed your code but for some reason the arc function does not return a face, so that follome can work, what am I missing?

The Ruby method Enumerable#grep returns an Array containing the matches, so your variable face is an Array containing the Face. This causes a undefined method error in torus because Array does not have a followme method! At some point you need to extract the face from the Array (and as a precaution should probably test whether grep returned an empty Array or and Array with more than one Face - which could happen if your model has previously drawn Faces!) Edit: in this case since you work within a new Group, you won’t find any Faces you didn’t just draw…

If you change arc() to arc()[0] you get this:

Thats great! Thank you for your input, I don’t have much of a ruby background but I’m churning along, thanks again!