Removing (Internal) Edges

I haven’t been posting on the development board for a while primarily because most of the ruby code I’ve been writing is tedious boring stuff.

However I’ve now have a (somewhat) interesting problem I’m working on. My goal is to generate a bunch of faces like what is shown below (wall outlines) all within the same group:

Where the walls are adjacent I will end up with internal edges that can be deleted. In fact, I want to delete all those internal edges so I just end up a single loop.

My question is does anyone have any idea for an algorithm that can detect if an edge is “internal”?

My first guess would be to examine each edge, get its two vertices and then for each vertex look at the number of edges that are connected to it. If the number of edges connected to the vertex is greater than two then the associated edge is internal.

Perhaps there is a better more efficient and more robust algorithm than what I have described?

P.S. I should add that there will the possibility that there will be internal loops within the outer loop, when the walls form a closed structure (not shown above).

temp = []
grp.entities.grep(Sketchup::Edge) do |e|
  temp << e if e.faces.size == 2
end
grp.entities.erase_entities( temp )

Did I misunderstand something?

3 Likes

Nice.

What is the upside to storing all of the edges into an array and then deleting all at once as opposed to deleting each edge as it is found?

You can see discussion about it here
https://forums.sketchup.com/t/why-this-error-and-how-to-correct-it/144303/22


BTW: In Partban’s code you will remove edges even the faces beside are no coo-planar…

You can check:
https://sketchucation.com/pluginstore?pln=FixIt_101
…how Anton is doing: Look for : “# Removes all coplanar and single edges.”


Edit
In addition you can check how ThomThom is doing it:
cleanup/core.rb at eaa4050c7f34d311ae59b50047d07e9f5ef63d2e · thomthom/cleanup · GitHub

1 Like

Perhaps…

togo = []
grp.entities.grep(Sketchup::Edge).each{|e|
  faces= e.faces
  togo << e if faces.length == 2 && faces[0].normal.parallel?(faces[1].normal)
  togo << e if faces.length == 0
}
grp.entities.erase_entities( togo )

To delete edges dividing coplanar faces and unfaced edges…

As a general rule "Don’t delete or change statement (|e| in our example) of a loop inside a loop. For more explanations in the following picture, imagine you find e1 first and delete it. When you check e2, it has only one face and you will not delete it. On other hand sometimes (especially in 3D) you delete e1 first result will be totally different from you delete e2 first then you see sometimes your codes work well and sometimes don’t. I recommend don’t risk and follow the general rule.

1 Like

It’s slightly faster to delete all of the collected entities in one go.

Provided that the collection is an array which has been separated from the original entities or selection context, then using e.erase! if e matches some test will also work, BUT this needs additional checks - such as mine where faceless edges are also processed - avoiding the issues raised when one edge [e.g. e1 has 2 faces] is deleted which changes the ‘status’ of the another edge [e.g. e2 which now has NO faces] …

I’d recommend entities.erase_entities(togos) method, unless you know the edges you’ll collect will be very limited in number and you also trap for the collected edges’ number of faces changing from 2 to 0 !

1 Like