Creating a cylinder?

Hi all,

I’m trying to create a cylinder, but I’m a little stuck. I try the following:

Let current_face be a reference to a face that is larger than the diameter, and diameter be a scalar. Model is the active_model.

 # Create a circle perpendicular to the normal
  vector = current_face.normal
  vector2 = vector.normalize!
  entities = model.entities
  edgearray = entities.add_circle current_face.bounds.center, vector2, diameter / 2
  face = entities.add_face(edgearray) #THIS IS NIL
  face.pushpull 5

The problem comes from trying to create a face from the edge array. It only returns a nil value. Why is this?

I haven’t done any Ruby, anywhere, let alone in SketchUp! But, you’re using the ! version of normalize, which would operate on ‘vector’, in place. The non-! version of normalize is the one that returns a normalized vector.

It could be that normalize! also returns the same value that the input vector has changed to, in which case even if you’re using a mixture of techniques, it ought to work.

The part that creates the circle is copied verbatim from the API definition, and everything up through the add_circle command is fine. The add_face command is the part that’s not working.

maybe start simpler…

model = Sketchup.active_model
entities = model.active_entities
centerpoint = Geom::Point3d.new
vector = Geom::Vector3d.new 0,0,1
edgearray = entities.add_circle centerpoint, vector, 2
face = entities.add_face(edgearray) 
face.pushpull 5

You only give us half the story…

You don’t need to bother to normalize the vector.
Also don’t use model.entities, when you might need to use model.active_entities IF the current_face is selected etc and might be in another context ?
Unless the current_face is a circle then it won’t have a center !
From the earlier code it’s a face ! [.normal]
So try current_face.bounds.center instead ??

PS: you haven’t defined what ‘diameter’ is - I assume it’s a length ?

RE: centers: Sorry, that is an error in my code on that I made when I tried to simplify it: the center is the center of the selected face’s bounds. I will fix that in the code.

I have narrowed down the problem to being when the circle is added DIRECTLY on an existing face. If I do this off of a face, it works fine.

It’s always a good Idea to add your new geometry inside a temporary group, that way you are sure of what you are working with…
So…

group=model.active_entities.add_group()
gents=group.entities

# then use ‘gents’ for adding your new geometry etc…
# at the end explode the group with…

group.explode
1 Like

I’m sorry, but this doesn’t really have anything to do with the question at all.

most likely, it’s because your adding edges to a pre-existing surface, and you loose reference to them, as they are now part of something else…
Tig’s add group suggestion is best way to hold a reference. because they are then the only ones available in that context…
It therefore has everything to do with you question even if you don’t understand that…
it would have been politer to ask why…

john

I’m sorry, as written, the answer is very vague and does not explain how it even pertains to the problem. Without context, it comes off completely as someone dismissing my question in favor of giving style suggestions.

The suggestion doesn’t actually solve the problem - I want to be able to extrude and intrude, and by creating a new group, it guarantees that this cylinder and its surface can never intersect. I ultimately want to be able to create a washer, and this method would not allow that.

You fail to understand my comments [and others].
If you create a temporary group and add your new geometry into that then it will not interact with existing entities.
Once you have done what you want you can merge your new geometry by exploding the group.

Rather than dismiss someones advice as, “…not having anything to do with the question…”, may I humbly suggest you reconsider your position.

My answer does ‘pertain’ to your issue.
Of course your new parts can ‘intersect’.
But of course, perhaps you need to make them do so in your code…
Why would a “washer” want to intersect anyway ?
Surely it’d be better as as separate ‘compnent’ [or group] ?

Try it and you might find it works… rather than ‘knowing’ it doesn’t and being impolite.

I end my help forthwith. :angry:

I think it’s because the face is already created when you created the circle. Create a circle with a face and add a circle, you automatically get two nested faces. Trying to add another face is redundant and you get a nil.

If you create the larger circle first, then the smaller circle, then the face for the larger circle, and then the face for the smaller circle, you will get the result that you expect. Deleting the smaller face and extruding the larger face gives this:

  model = Sketchup.active_model
  entities = model.active_entities
  center = [0,0,0]
  vector = [0,0,1]
  radius = 2.0
  big_edges = entities.add_circle center, vector, radius
  small_edges = entities.add_circle center, vector, radius / 2.0
  big_face = entities.add_face(big_edges) 
  small_face = entities.add_face(small_edges)
  small_face.erase!
  big_face.reverse!
  big_face.pushpull 5.0

BTW, I’ve found Ruby to be more friendly if I use something like “diameter / 2.0” to force non-integer activity.

[added later]

If you want to add the circle to an existing face and delete the center of the washer, you might try something like this:

  model = Sketchup.active_model
  entities = model.active_entities
  center = [0,0,0]
  vector = [0,0,1]
  radius = 2.0
  big_edges = entities.add_circle center, vector, radius
  big_face = entities.add_face(big_edges) 
  small_edges = entities.add_circle center, vector, radius / 2.0
  faces = small_edges[0].faces
  faces[0].erase!
  big_face.reverse!
  big_face.pushpull 5.0

[added much later]

An alternate method to deleting the center face … since the addition of the smaller circle intersects the larger face and, as a result, adds another face to the entities, you can simply erase the last item added instead of using an edge to find the adjacent faces:

  model = Sketchup.active_model
  entities = model.active_entities
  center = [0,0,0]
  vector = [0,0,1]
  radius = 2.0
  height = 5.0
  big_edges = entities.add_circle center, vector, radius
  big_face = entities.add_face(big_edges) 
  entities.add_circle center, vector, radius / 2.0
  entities[-1].erase!
  big_face.reverse!
  big_face.pushpull height

An observation:

The API documentation says that the “add_face” command returns “a Face object if successful.” In the context of your particular use, the face is not created and the command returns nil. While this might be unexpected behavior, it doesn’t conflict with the description of the function.

[one more thing (my co-workers groan and roll their eyes when they hear me say this)]

Back to your original code … I modified it slightly to work around the nil issue:

  model = Sketchup.active_model
  entities = model.active_entities
  current_edges = entities.add_circle [0,0,0], [0,0,1], 2.0
  current_face = entities.add_face(current_edges)
  diameter = 2.0
#--------
  vector = current_face.normal
#  vector2 = vector.normalize!
#  entities = model.entities
  edgearray = entities.add_circle current_face.bounds.center, vector, diameter / 2.0
  face = entities.add_face(edgearray)
  if(face == nil)
    face = entities[-1]
  end
  face.pushpull 5.0

If you want to create a ‘donut’ ring-shape, and then ‘extrude’ it using PushPull, then the order of operations become very important.

Make everything inside a [temporary] group - this ensures that any new geometry is kept separated from other parts; it’s also easier to keep tabs of the new geometry…

group=entities.add_group()

Now use iedges=group.entities.add_circle(...) to form the inner edges of the donut - collecting its edges as you do so.
Then use iface=group.entities.add_face(iedges)
You need the reference to that face ‘hole’ a little later as you will erase it after forming the ring.
Now add the larger circle to form the outer part of the ring, again collecting its edges as you do so.
Use edges=group.entities.add_circle(...)
Use edges[0].find_faces to infill the donut with a face
You now have two faces - one unreferenced forming the donut ring, and the other one being the the unwanted ‘hole’.
Using the reference to the ‘hole’ face now erase it.
Using iface.erase!
Now there is only one face in the group - face=group.entities.grep(Sketchup::Face)[0]
Now you can use face.pushpull(...) as desired…
Finally explode the temporary group as desired…

Great explanations.in this “face off”, I am trying to add line Edges (more than 1) to an arc. I seem to have trouble. Can you illustrate a simple example? (appreciated. is there a way to convert edges to 3D points, and vice versa?) thx great 2016

Given an “edge”, you can access “edge.start.position.point” and “edge.end.position.point” to get the start and end points of an edge (see here and here for more info).

Given two points, pt1 and pt2, you can create an edge with something like “entities.add_line(pt1,pt2)” or “entities.add_edges(pt1,pt2)”. The first one creates only a single edge. The second flavor allows you to pass an array of points to create a chain of edges (see here and here for more info).[quote=“sannerwind, post:14, topic:14800”]
Can you illustrate a simple example?
[/quote]

entities = Sketchup.active_model.active_entities
pt1 = [0,0,0]
pt2 = [1,0,0]
pt3 = [1,1,0]
pt4 = [0,1,0]
entities.add_edges([pt1,pt2,pt3,pt4,pt1])