Create and extrude circles using the selected guide points as centers

Hello Community,

I’m a beginner with Ruby scripting for SketchUp. I’m working on a script that draws two circles from selected guide points and extrudes the smaller circle. So far, the script is able to create both circles, but I run into an issue when trying to extrude the inner circle.

Here’s the script:

module GuidePointsToCircles
  def self.create_circles_from_guides
    model = Sketchup.active_model
    selection = model.selection

    model.start_operation("Create Circles from Guide Points", true)

    guide_points = selection.grep(Sketchup::ConstructionPoint)

    if guide_points.empty?
      UI.messagebox("No guidepoints have been selected! Please select guidepoints and start again.")
      model.abort_operation
      return
    end

    radius_1 = 5.cm
    radius_2 = 2.5.cm
    normal = [0, 0, 1]

    entities = guide_points.first.parent.entities
    positions = guide_points.map(&:position)

    positions.each do |center|
      entities.add_circle(center, normal, radius_1, 24)
      entities.add_circle(center, normal, radius_2, 24)
    end

    model.commit_operation
  end
end

GuidePointsToCircles.create_circles_from_guides

I then attempt to extrude the second circle with:

face = entities.add_face(circle)
face.pushpull(1.cm)

But I get the following error message:
<NoMethodError: undefined method `pushpull’ for nil:NilClass>

Does anyone know why I can’t extrude the second circle? Any suggestions on how to fix this?

Thanks in advance for your help!

You missed to add reference to that circle
The add_circle method is returns an Array object containing edges.
This array of edges need to be passed to add_face method as parameter. So you can pushpull that face which returned by add_face method.

        .
        circle = entities.add_circle(center, normal, radius_2, 24)
        face = entities.add_face(circle)
        face.pushpull(1.cm)
        .
1 Like

Thank you @dezmo for the clarification.

Here is the modified script:

module GuidePointsToCircles
  def self.create_circles_from_guides
    model = Sketchup.active_model
    selection = model.selection

    model.start_operation("Create Circles from Guide Points", true)

    guide_points = selection.grep(Sketchup::ConstructionPoint)

    if guide_points.empty?
      UI.messagebox("No guidepoints have been selected! Please select guidepoints and start again.")
      model.abort_operation
      return
    end

    radius_1 = 5.cm
    radius_2 = 2.5.cm
    normal = [0, 0, 1]

    entities = guide_points.first.parent.entities
    positions = guide_points.map(&:position)

    positions.each do |center|
      entities.add_circle(center, normal, radius_1, 24)

      circle = entities.add_circle(center, normal, radius_2, 24)
      face = entities.add_face(circle)
      face.pushpull(1.cm)
    end

    model.commit_operation
  end
end

GuidePointsToCircles.create_circles_from_guides

I still get the following error though:

#<NoMethodError: undefined method pushpull' for nil:NilClass>
=> nil

Am I still doing something wrong?

1 Like

I guess you are using Ruby Console+ or Ruby Code Editor extension.

Use the native Ruby Console. After selecting the guide points, copy-paste your code into native Ruby Console it and hit enter.

Share your model on which you are testing, perhaps something wrong with that.

For me, your code works:

testcode

1 Like

Thank you @dezmo,

you’re right, it works on the native Ruby Console!

1 Like

Works on the Ruby Console for me too. That leaves the mystery of what is wrong with how you were previously launching it. You never said exactly what you did or what code editor you were using.

I was using Ruby Code Editor extension.

Best practice with the Entities factory methods are to always check the return value for “truthiness” as nil will be returned if the geometry creation fails.

You could have a clause in a conditional expression that attempts to recover gracefully or notify the user that the face creation failed.

You could also just have the minimum “truthy” check that would prevent the exception, thus:

      face.pushpull(1.cm) if face

Or … using Ruby’s safe navigation operator (&.):

      face&.pushpull(1.cm)

The &. operator will not call the method if the receiver object is nil. (Beware it will call the method if the receiver is false and raise an exception if the method is unknown to the singleton instance of FalseClass.)