How to force ruby to interact with selected edges in order of creation? – Ruby API


How to force ruby to interact with selected edges in order of creation?

I have a small code piece to get a flat shape made by some edges and connect each point of edges to the Origin:

model = Sketchup.active_model
selection = model.selection
y=0
p_arr = Array.new(100)
selection.each { |entity| 
  if entity.is_a?(Sketchup::Edge)
    	vertex = entity.end
	p_arr[y] = vertex.position
	y+=1
    puts vertex.position
	model.entities.add_line [0,0,0], vertex.position
	UI.messagebox "P"  
end
}
puts y.to_s

video1

The code works but as you can see in attached video, the nodes are not connected to Origin in order of creation. sometimes the oldest line of face is the first one which connects to Origin. What I want is to force my code to connect points to Origin from oldest to newest. is there any solution for this?
Thank you in advance for your help.

Hey here is a guide on how to properly post code in the forum:

Your Code:

model = Sketchup.active_model
selection = model.selection
y=0
p_arr = Array.new(100)
selection.each { |entity|
if entity.is_a?(Sketchup::Edge)
vertex = entity.end
p_arr[y] = vertex.position
y+=1
puts vertex.position
model.entities.add_line [0,0,0], vertex.position
UI.messagebox “P”
end
}
puts y.to_s

Sorry I have no other advice, perhaps someone with more knowledge than I can help…



1 Like

There is no way to determine selected edges in order of creation (unless you write complex code with complicated observers…) Neither the order of the selected entities. Moreover, the order of entities in the set is in no particular order and should not be assumed to be in the same order as the user selected the entities.

However, you can assume the vertices of the outer loop of a face are in order.



3 Likes

SketchUp has no inherent concept of “order of creation”. Because it shares vertices between edges and edges between faces, it feels free to rearrange and/or recreate them whenever that suits its immediate needs. Also, many of its collection classes use other data types than Arrays beneath the Ruby wrappers, which again does not assure retrieval in the same order as addition.

In your video, you appear to select by double-clicking on the face created by the edges. There is no way to assure what order this will put the edges into the selection. Even selecting just the edges one-by-one won’t assure any particular order in the selection.

As @dezmo noted, if you use the face’s outer loop vertices instead of the edges, you can at least be certain they will be in counter-clockwise order around the face’s normal, though you can’t be assured that the sequence will start with some particular vertex of interest to you.

You could achieve the desired effect if you wrote a custom line Tool that kept track of the points clicked in order, though that’s a lot more work than the simple snippet you posted.



1 Like

Thank you @slbaumgartner, @dezmo
For the purpose that I have in mind, the custom line tool will be a quick and good solution as I always create my faces using line tool and no automatic process involved. I can create lines to origin right in time of using custom line tool to build the face.
Thanks again.

Some other advise:

You do not need to predefine the (oversized) array.
p_arr = Array.new
or more simple:
p_arr = []

You can use

selection.each_with_index { |entity,y| 
  #...
}

But even you do not need use indices
if you push / append the element into the array:

p_arr.push( vertex.position )
or
p_arr.append( vertex.position )
or
p_arr<< vertex.position

References:
Class: Array (Ruby 2.7.1) (ruby-doc.org)
Module: Enumerable (Ruby 2.7.1) (ruby-doc.org)



2 Likes

Thanks for useful comments.
Obviously I am a beginner and believe it or not, sometimes the ghost of GW-Basic haunts me.



Source link

Leave a Comment