Drawing something more complex than a cube with Ruby

Because the operation can create multiple faces so it returns an integer number of faces created.

Well that is because Enumerable#grep always returns an Array object, not a face.
(In some cases it might be an empty array.)

ADD: The NoMethodError happens because #pushpull is a method of the Sketchup::Face class not the Array class.

So the solution is simple. Array snapshot and subtract using Array#-.

faces_before = entities.grep(Sketchup::Face)
edge4.find_faces
new_faces = entities.grep(Sketchup::Face) - faces_before
unless new_faces.empty?
  # do some code with the new faces in the array
end

EDIT (ADD): We often wonder why the API writers didn’t just return an array of the new faces created, because that is what everyone wants. The small number of situations where the number needs to be known can simply get the size of the returned array.

1 Like

In some operations previous (before) references may become invalid,
so check your collections of entities often at strategic times …

# SketchUp 2014+
faces.keep_if(&:valid?)

# older SketchUp using Ruby 1.8.x
faces.keep_if {|face| face.valid? }

It works!

Capture

Thanks Dan.

1 Like

Ok, one more question. Instead of reversing the direction of the lines, I decided to reverse the direction of the arcs, so everything is going counter-clockwise (I think I’ll fix that to clockwise later). Without fixing the lines, you can see how everything was backwards, with corner3 being the only one correct:


Here’s the funny thing:

roundcorner2 = entities.add_arc(
  Geom::Point3d.new(1-0.25, 0.25, 0), 
  X_AXIS, 
  Z_AXIS, 
  0.25, 
  270.degrees, 
  360.degrees, 
  8)
roundcorner3 = entities.add_arc(
  Geom::Point3d.new(1-0.25, 1-0.25, 0), 
  X_AXIS, 
  Z_AXIS, 
  0.25, 
  0.degrees, 
  90.degrees, 
  8)

Notice how how corner2’s second angle is 360°, while corner3’s first angle is 0°? Wanna know what happens if you use 360° for corner 3 to be consistent?


Same thing happens to corner2 if you use 0°.

:confused: boggles

I think it’s time for bed.

That is not being consistent.

You specified an 270 degree arc sweeping clockwise (instead of a 90 degree arc sweeping counter-clockwise.)
So of course it will look like that.

Definately time for bed.

Maybe it seems that way to you, but to me I just punched numbers until I got something with the end result I wanted. The problem is I don’t understand what I’m doing. I’m not understanding how the references to the axis and angles is working. Is the below image correct? If so, why does one work with 0° and the other not?
Capture

Well, first of all do not equate 0 degrees with “North” (that will just add confusion.)

Traditionally CAD software and many code libraries, work with angles measured counter clockwise looking down on the “paper”. (It always seemed weird to me.)
I can guess however it has to do with Cartesian coordinate math. Remember that from High School?
The X axis pointing to the right was always the 0 vector. 90 degrees pointing “up” along the Y axis, … etc.

The angle swept between start and end.

The angle swept from 0 to 90 is 90, and must be swept counter-clockwise.
The angle swept from 360 to 90 is 270, and must be swept clockwise.

You may be missing the idea that you could reuse the same code to draw each 90 degree corner, by just rotating the x axis vector for each corner.

So going clockwise …

module CraftyHippo

  extend self

  def draw_arc(ents,center,vector,radius)
    ents.add_arc( center, vector, Z_AXIS, radius, 90.degrees, 0.degrees ).first.curve
  end

  def draw_round_square(ipoint,width,height,radius)
    # ipoint = insertion point at lower left
    xside = width - (2*radius)
    yside = height - (2*radius)
    arcs = []
    model = Sketchup.active_model
    ents  = model.active_entities
    #
    model.start_operation("Draw Rounded Square")
      #
      center = ipoint.transform([radius,radius,0])
      arcs << draw_arc(ents,center,[-1,0,0],radius)
      #
      center = center.transform([0,yside,0])
      arcs << draw_arc(ents,center,[0,1,0],radius)
      #
      center = center.transform([xside,0,0])
      arcs << draw_arc(ents,center,[1,0,0],radius)
      #
      center = center.transform([0,-yside,0])
      arcs << draw_arc(ents,center,[0,-1,0],radius)
      #
      for i in 1..4
        ents.add_line(
          arcs[i-1].last_edge.end.position,
          arcs[ i==4 ? 0 : i ].first_edge.start.position
        )
      end
      #
      arcs[0].first_edge.find_faces
      #
    model.commit_operation
    #
  end

end

And running it at the console …

CraftyHippo.draw_round_square(ORIGIN,5,5,1)

P.S. - In the example above I’m using arrays in place of points, vectors and transformations.
The API has made the Array class compatible with these classes of objects. Ie …

Class: Array — SketchUp Ruby API Documentation

The SketchUp Array class adds additional methods to the standard Ruby Array class. Specifically, it contains methods allowing an array to behave just as a Geom::Vector3d or Geom::Point3d object (which can be thought of as arrays of 3 coordinate values). Therefore, you can use the Array class in place of a Geom::Point3d or Geom::Vector3d as a way to pass coordinate values.

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.