Smooth / Soft group edges

Why does this code take a long time and runing SketchUp menus the effect is immediate? Is there any instructions to do the same directly, like group.soft=true / group.smooth=true?

model = Sketchup.active_model
selection = model.selection
edges=[]
selection.to_a.each{|e|
   edges << e if e.class==Sketchup::Edge
   e.entities.each{|ee|edges << ee if ee.class==Sketchup::Edge}if e.class==Sketchup::Group
}
edges.each{|edge|
ang=edge.faces[0].normal.angle_between(edge.faces[1].normal)
   if edge.faces[1]
     edge.soft=true if ang < 20.degrees
     edge.smooth=true if ang < 20.degrees
   end

The #soft and the #smooth instance methods can be apply only for the edges. You have to do recursively similar as in your exampleā€¦ however I think it could be optimized more.

As far as i know, since Ruby API is just a wrapper on top of C++ core, I guess, the ā€œSketchUp menus the effect is immediateā€ is much more effective because it written naively in C++ ā€¦ (But Iā€™m not much familiar with thisā€¦ even Iā€™m not really sure if it s C++ at all :wink: )

Extract the group[s] from the selectionā€¦

model = Sketchup.active_model
selection = model.selection
groups = selection.grep(Sketchup::Group)
### now examine the selected group[s] entities for suitable edges...
groups.each{|group|
  edges = group.entities.grep(Sketchup::Edge)
  edges.each{|edge|
    ang = edge.faces[0].normal.angle_between(edge.faces[1].normal)
    if edge.faces[1]
      edge.soft=true if ang < 20.degrees
      edge.smooth=true if ang < 20.degrees
    end
  }
}
2 Likes

It would be better to put the angle calculation inside the if-end

Try adding

model.start_operation("Soften/Smooth Edges", true)

and

model.commit_operation

around your model changes to prevent the view from redrawing at each change.

1 Like

@dezmo
How about this to minimize the ā€˜testingā€™ and weirdness with multi-faced edges? ā€¦

###...
edges.each{|edge|
    if edge.faces.length == 2
      ang = edge.faces[0].normal.angle_between(edge.faces[1].normal)
      if ang < 20.degrees
        edge.soft=true
        edge.smooth=true
      end
    end
  }
###

@ene_su
Clearly the OPā€™s post is just a snippet of codeā€¦
It needs to be enclosed inside its own modules[s] and as you suggest the model.start/commit_operations need adding to ensure undoing etcā€¦

2 Likes

I like it tooā€¦and I like Ruby because it can be infinitely variedā€¦ :slight_smile: (the grep have itā€™s ā€œownā€ each ā€œbuilt inā€ and so onā€¦ )

model = Sketchup.active_model
selection = model.selection
model.start_operation("Soften/Smooth Edges", true)
selection.grep(Sketchup::Group){|gr|
  gr.entities.grep(Sketchup::Edge){|e|
    if e.faces[1] && e.faces[0].normal.angle_between(e.faces[1].normal) < 20.degrees
      e.soft=true
      e.smooth=true
    end
  }
}
model.commit_operation
2 Likes

This is called multi-paradigm. (The i is long and the g is silent.)


The only thing Iā€™d change to speed it up a bit, is to not force Ruby to create the edgeā€™s face array 3 times.

model = Sketchup.active_model
selection = model.selection
model.start_operation("Soften/Smooth Edges", true)
  selection.grep(Sketchup::Group) { |gr|
    gr.entities.grep(Sketchup::Edge) { |e|
      f = e.faces
      if f[1] && f[0].normal.angle_between(f[1].normal) < 20.degrees
        e.soft=true
        e.smooth=true
      end
    }
  }
model.commit_operation
3 Likes

model.start_operation("Soften/Smooth Edges", true)

and

model.commit_operation

That command really helps. Thank you to everyone.

3 Likes