SU freezes when creating lines - ruby plugin

#1

Hi. I am reading lines from a simple file. That works ok, as i created messages to Sketchup.set_status_text to be sure what`s going on. But, when i actually create the lines from the array, the program freezes. It freeze only above 30k lines more or less.

This is the loop in which the problem occurs:

for c in 1…$edges_count
this_edge = edges_array[c - 1]

			new_model.active_layer = this_edge[2]
							
			entities_edges.add_edges(this_edge[0], this_edge[1])
		end
#2

First of all. Generally in SketchUp, all geometric primitives (faces, edges, arcs, polygons) should be associated with “Layer0”. Only group and component instance containers should be associated with other layers. (ie, layers are not geometric containers in SketchUp. Only groups and component instances separate geometry.)

2.) Coding questions go in the forum’s Developers > Ruby API subcategory.
(Admins have reassigned to correct category.)

3.) Please wrap code correctly in forum … [How to] Colourize code on the forum? (wiki)

This is know to occur when Ruby has a lot of work to do.
So use a model undo operation and set the 2nd argument true to disable the UI.


Poor example ... click to view. (See better example below.)
for c in 1…$edges_count
  this_edge = edges_array[c - 1]
  model.start_operation("Draw edges",true)
  ###
    #
    entities_edges.add_edges(this_edge[0], this_edge[1])
    #
  ###
  model.commit_operation
end
#3

EDIT: Actually the above example is not ideal as the undo operation is inside a loop, and will create too many operations. The loop needs to be inside the operation, like so …

model.start_operation("Draw edges",true)
###
  #
  for c in 1…$edges_count
    this_edge = edges_array[c - 1]
    entities_edges.add_edges(this_edge[0], this_edge[1])
  end
  #
###
model.commit_operation
#4

Thats exactly the way it is written. But still will freeze. In fact, it appears the rotating wheel of death, but i discovered that, for example, for 200.000 lines, it took half and hour and finally made it, so it was not freezed, it was working and being extremely slow. (1 second for 20k lines, 30 minutes for 200k lines). After reading the posts related to my issue i see that ruby gets slow for this kind of issues. I would like to know if this is normal, the time used, and if i should redirect my efforts into trying the program not to show the wheel (which reading also is difficult), or if there is something im missing. I`m surprised because this is a super basic task, (adding edges). Any other ideas? thank you so much for your responses.

#5

Don’t be surprised. The more edges you add into a geometry context, the more work SketchUp must do to check if there are any edge or face intersections. With each edge added, the entities collection gets bigger, making the intersection check longer and longer.

SketchUp is unique from CAD in that it has “sticky” geometry, so each time you add a face or edges, SketchUp must check if they will intersect any current geometry.

You might try creating a group or component, and adding edges to that instead of the model’s main entities collection.

Create Geom::Point3d objects instead of arrays with numeric values for your vertices used for making the edges.

Or use the Geom::PolygonMesh helper class.


Also, I did not notice before but do not use $var as they are global and can clash.

ALL of your code should be wrapped within your own namespace module. So use either a module var @@var or a instance @var for persistent references.

You can simplify the loop somewhat …
(to eliminate the unneeded Range object and assignment using a math expression) …

model.start_operation("Draw edges",true)
###
  #
  for this_edge in edges_array
    entities_edges.add_edges(this_edge[0], this_edge[1])
  end
  #
###
model.commit_operation
#6

can you post an example array to make testing easier for others…

I use the view to show progress even if it’s beach-balling…

pts_ary = []
(1..10000).each_cons(3) {|pt| pts_ary << pt[0..1]}

model = Sketchup.active_model
ents  = model.entities
view  = model.active_view
model.start_operation("Draw edges",true)
pts_ary.each_slice(10) do |slice|
  ents.add_edges(slice)
  view.refresh
end

model.commit_operation

john

#7

Hey John, so you go showing the progress on screen ? Maybe that is slower but at least it will not show the rolling wheel of freezing ??

that slice thing means that the view will freeze each 10 lines are drawn ?

thank you !

#8

my understanding [which may be delusional ], is that each slice [ be it 10, 100 ,1000, etc… ] will empty the buffer that accumulates the edges waiting to be drawn…

the view doesn’t freeze, it just waits till slice end and refreshing it with the new geometry shows that ruby is also not frozen…

I sometimes comment out the refresh, when everything else is working and compare timings…

for some of mine [on a mac] it is quicker with refresh, than without…

john

#9

The trick is instead of adding edges,
create a mesh and use the fill_from_mesh method (http://ruby.sketchup.com/Sketchup/Entities.html#fill_from_mesh-instance_method) This is much faster because SketchUp does a lot less checking. If you need edges and no faces the trick is to create a face with the third point the same like the first point. The result will be an edge in SketchUp.

We used this trick to create dashed lines in Skalp (before we had linestyles)

2 Likes