Followme with the SketchUp API
-
I am trying to create (rebar) with the follow me tool in the API. I have a rectangle path with arcs at the corners. I've been fighting with this for hours now and I can't seem to get it to work. My chunk of code is below:
@Tbarbr = @Topbardia * 6.0 @Topbarradius = @Topbardia/2.0 arc1x = @Ftgx1 + @Ftgwidth/2.0 + @Tbarbr arc1y = @Ftgx1 + @Ftgwidth/2.0 + @Tbarbr arc1z = @Slaby1 - @Rebar_clr arc2x = @Ftgx1r - @Ftgwidth/2.0 - @Tbarbr arc2y = @Ftgx1 + @Ftgwidth/2.0 + @Tbarbr arc2z = @Slaby1 - @Rebar_clr arc3x = @Ftgx1r - @Ftgwidth/2.0 - @Tbarbr arc3y = @Ftgx1b - @Ftgwidth/2.0 - @Tbarbr arc3z = @Slaby1 - @Rebar_clr arc4x = @Ftgx1 + @Ftgwidth/2.0 + @Tbarbr arc4y = @Ftgx1b - @Ftgwidth/2.0 - @Tbarbr arc4z = @Slaby1 - @Rebar_clr center1 = Geom;;Point3d.new arc1x, arc1y, arc1z center2 = Geom;;Point3d.new arc2x, arc2y, arc2z center3 = Geom;;Point3d.new arc3x, arc3y, arc3z center4 = Geom;;Point3d.new arc4x, arc4y, arc4z # centercircle = Geom;;Point3d.new arc1x, (@Ftgx1 + @Ftgwidth/2.0), arc1z centercircle = Geom;;Point3d.new (@BuildingWidth/2.0), (@Ftgx1 + @Ftgwidth/2.0), arc1z lp1s = [arc1x, (@Ftgx1 + @Ftgwidth/2.0), arc1z] lp1m = [(@BuildingWidth/2.0), (@Ftgx1 + @Ftgwidth/2.0), arc1z] lp1e = [arc2x, (@Ftgx1 + @Ftgwidth/2.0), arc1z] lp2s = [(@Ftgx1r - @Ftgwidth/2.0), arc2y, arc1z] lp2e = [(@Ftgx1r - @Ftgwidth/2.0), arc3y, arc1z] lp3s = [arc1x, (@Ftgx1b - @Ftgwidth/2.0), arc1z] lp3e = [arc2x, (@Ftgx1b - @Ftgwidth/2.0), arc1z] lp4s = [(@Ftgx1 + @Ftgwidth/2.0), arc2y, arc1z] lp4e = [(@Ftgx1 + @Ftgwidth/2.0), arc3y, arc1z] normal = Geom;;Vector3d.new 0,0,1 xaxis = Geom;;Vector3d.new 1,0,0 start_a1 = 3.14159265358979 end_a1 = 4.71238898038 start_a2 = 4.71238898038 end_a2 = 6.28318530718 start_a3 = 0.0 end_a3 = 1.5707963268 start_a4 = 1.5707963268 end_a4 = 3.14159265358979 grouptb1 = Sketchup.active_model.active_entities.add_group entitiestb1 = grouptb1.entities grouptb1.description = "REBAR TOP 1" grouptb1.name = "REBAR TOP 1" edgearray = entitiestb1.add_arc center1, xaxis, normal, @Tbarbr, start_a1, end_a1 edge1 = edgearray[0] arccurve1 = edge1.curve edgearray = entitiestb1.add_arc center2, xaxis, normal, @Tbarbr, start_a2, end_a2 edge2 = edgearray[0] arccurve2 = edge2.curve edgearray = entitiestb1.add_arc center3, xaxis, normal, @Tbarbr, start_a3, end_a3 edge3 = edgearray[0] arccurve3 = edge3.curve edgearray = entitiestb1.add_arc center4, xaxis, normal, @Tbarbr, start_a4, end_a4 edge4 = edgearray[0] arccurve4 = edge4.curve line1a = entitiestb1.add_line lp1s, lp1m line1b = entitiestb1.add_line lp1m, lp1e line2 = entitiestb1.add_line lp2s, lp2e line3 = entitiestb1.add_line lp3s, lp3e line4 = entitiestb1.add_line lp4s, lp4e # topbaredges = [line1b, arccurve2, line2, arccurve3, line3, arccurve4, line4, arccurve1, line1a] topbaredges = [line1b, edge2, line2, edge3, line3, edge4, line4, edge1, line1a] # path_face = entitiestb1.add_face(topbaredges) # path_edges = path_face.all_connected topcircle = entitiestb1.add_circle centercircle, xaxis, @Topbarradius top_face = entitiestb1.add_face(topcircle) status_top_bar = top_face.followme(topbaredges)
-
Here is what the path and face to extrude looks like:
-
Manually, using the follow me tool, I can extrude it along the path just fine. My code though does not seem to work but yet it does not throw any error in the ruby console.
-
Replaced the 6th line from the bottom with this:
topbaredges = line1b.all_connected
and now it works.
-
So, it was failing because you were setting
edge1
,edge2
,edge3
andedge4
, to reference only the first segment of their respective arccurve, ...... which caused the edge array
topbaredges
to have a set of 4 disconnected edge paths.There are two easy ways around this.
First assume you had set each arc edge array to a reference like
arc1edges
,arc2edges
, etc., from theadd_arc()
method call.(Scenario A) - You create a literal nested array for your
followme()
method call, but flatten it using theArray
class'flatten()
method.Ie, your literal edge array
topbaredges
would be defined like:topbaredges = [ line1b, arc2edges, line2, arc3edges, line3, arc4edges, line4, arc1edges, line1a ].flatten
This should result in a 1 level array of all edge objects. (It is always good to test collections just in case. For example:
if topbaredges.any? {|o| !o.is_a?(Sketchup::Edge) }
will returntrue
if there is a non-edge object in the collection.)
(Scenario B) - You use Ruby's built-in "splat" operator. It's the
*
character. It can convert an array to a parameter list, or a parameter list to an array.Example:
` ary1 = [2,3,4]
ary2 = [6,7,8]
ary3 = [10,11,12]ary = [ 1, *ary1, 5, *ary2, 9, *ary3, 13, 14 ]`
sets [ruby:1bj806zx]ary[/ruby:1bj806zx] to:
[ruby:1bj806zx][1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14][/ruby:1bj806zx]So, [ruby:1bj806zx]*ary1[/ruby:1bj806zx] expands the array into the parameter list [ruby:1bj806zx]2, 3, 4[/ruby:1bj806zx], etc. (You'll often see this syntax used for method definitions to collect arguments into a method-local array. So, not only can you use it in literal expressions, but also in method call parameter lists.)
So, you could use this syntax (instead of the [ruby:1bj806zx]Array#flatten()[/ruby:1bj806zx] method.)
Ie, your literal edge arraytopbaredges
would be defined like:topbaredges = [ line1b, *arc2edges, line2, *arc3edges, line3, *arc4edges, line4, *arc1edges, line1a ]
-
Thank-you for providing clarity on this problem. I can't believe I didn't figure it out the answer was right in front of me. I guess the problem was that I wasn't fully understanding the "arc" construct. Now I realize that it is simply an array of edges, and can be manipulated as such.
One final issue with this follow me application is that the surface generated is inside out (reversed), what would be the best way to prevent this or reverse it. The follow me call does not output the handle to surface so there is no easy way do this at least from a cursory inspection of the code.
-
top_face.reverse!() if (top_face.normal.z < 0)
-
Or perhaps
top_face = entitiestb1.add_face(topcircle) top_face.reverse! if top_face.normal.samedirection?(topbaredges[0].line[1] status_top_bar = top_face.followme(topbaredges)
Advertisement